Optymalizacja obciążenia w projekcie Highload za pomocą ElasticSearch

Hej Habra! Nazywam się Maxim Vasiliev, pracuję jako analityk i kierownik projektów w firmie FINCH. Dzisiaj chciałbym Wam opowiedzieć, jak dzięki ElasticSearch udało nam się przetworzyć 15 milionów zapytań w 6 minut i zoptymalizować dzienne obciążenia strony jednego z naszych klientów. Niestety będziemy musieli obejść się bez nazwisk, ponieważ mamy NDA, mamy nadzieję, że treść artykułu na tym nie ucierpi. Chodźmy.

Jak działa projekt

Na naszym backendzie tworzymy usługi zapewniające wydajność stron internetowych i aplikacji mobilnej naszego klienta. Ogólną strukturę można zobaczyć na schemacie:

Optymalizacja obciążenia w projekcie Highload za pomocą ElasticSearch

W trakcie pracy przetwarzamy dużą liczbę transakcji: zakupów, płatności, operacji z saldami użytkowników, dla których przechowujemy wiele logów, a także importujemy i eksportujemy te dane do zewnętrznych systemów.

Istnieją również procesy odwrotne, gdy otrzymujemy dane od klienta i przekazujemy je użytkownikowi. Ponadto nadal istnieją procesy pracy z programami płatności i premii.

Krótkie tło

Początkowo używaliśmy PostgreSQL jako jedynego magazynu danych. Jego standardowe zalety dla systemu DBMS: obecność transakcji, rozwinięty język próbkowania danych, szeroka gama narzędzi do integracji; w połączeniu z dobrą wydajnością zaspokaja nasze potrzeby na dość długi czas.

W Postgres przechowywaliśmy absolutnie wszystkie dane: od transakcji po aktualności. Ale liczba użytkowników rosła, a wraz z nią liczba żądań.

Dla zrozumienia roczna liczba sesji w 2017 tylko na stronie desktopowej to 131 mln. W 2018 - 125 mln. 2019 ponownie 130 mln. Dodaj kolejne 100-200 mln z mobilnej wersji serwisu i aplikacji mobilnej i masz otrzyma ogromną liczbę żądań.

Wraz z rozwojem projektu Postgres przestał sobie radzić z obciążeniem, nie mieliśmy czasu - pojawiła się duża ilość różnych zapytań, dla których nie mogliśmy stworzyć wystarczającej liczby indeksów.

Zrozumieliśmy, że potrzebne są inne magazyny danych, które zaspokoiłyby nasze potrzeby i odciążyłyby PostgreSQL. Jako możliwe opcje uznano Elasticsearch i MongoDB. Ten ostatni przegrał w następujących punktach:

  1. Niska prędkość indeksowania wraz ze wzrostem ilości danych w indeksach. Dzięki Elastic prędkość nie zależy od ilości danych.
  2. Brak wyszukiwania pełnego tekstu

Wybraliśmy więc Elastic dla siebie i przygotowaliśmy się na przejście.

Przejście na elastyczne

1. Rozpoczęliśmy przejście z usługi wyszukiwania punktów sprzedaży. Nasz klient posiada łącznie około 70 000 punktów sprzedaży, a to wymaga kilku typów wyszukiwań w serwisie i w aplikacji:

  • Wyszukiwanie tekstu według nazwy miasta
  • Geowyszukiwanie w określonym promieniu od pewnego punktu. Na przykład, jeśli użytkownik chce zobaczyć, które punkty sprzedaży znajdują się najbliżej jego domu.
  • Wyszukiwanie po zadanym kwadracie – użytkownik rysuje na mapie kwadrat i pokazane są mu wszystkie punkty w tym promieniu.
  • Szukaj według dodatkowych filtrów. Punkty sprzedaży różnią się od siebie asortymentem

Jeśli mówimy o organizacji, to w Postgresie mamy źródło danych zarówno dla mapy, jak i wiadomości, aw Elastic Snapshots są pobierane z oryginalnych danych. Faktem jest, że początkowo Postgres nie był w stanie poradzić sobie z wyszukiwaniem według wszystkich kryteriów. Nie tylko było wiele indeksów, ale mogły one również nakładać się na siebie, więc program planujący Postgres zgubił się i nie wiedział, którego indeksu użyć.

2. Następna w kolejce była sekcja aktualności. Publikacje pojawiają się w serwisie codziennie, aby użytkownik nie zgubił się w natłoku informacji, dane muszą zostać posortowane przed wydaniem. Do tego właśnie służy wyszukiwanie: możesz przeszukiwać witrynę według dopasowania tekstu, a jednocześnie podłączyć dodatkowe filtry, ponieważ są one również tworzone przez Elastic.

3. Następnie przenieśliśmy przetwarzanie transakcji. Użytkownicy mogą kupić określony produkt na stronie i wziąć udział w losowaniu nagród. Po takich zakupach przetwarzamy dużą ilość danych, szczególnie w weekendy i święta. Dla porównania, jeśli w zwykłe dni liczba zakupów waha się w granicach 1,5-2 mln, to w święta liczba ta może sięgać 53 mln.

Jednocześnie dane muszą być przetwarzane w jak najkrótszym czasie – użytkownicy nie lubią czekać na wynik przez kilka dni. Przez Postgres nie ma możliwości dotrzymania takich terminów - często otrzymywaliśmy blokady, a podczas rozpatrywania wszystkich zgłoszeń użytkownicy nie mogli sprawdzić, czy otrzymali nagrody, czy nie. Nie jest to zbyt przyjemne dla biznesu, dlatego przenieśliśmy przetwarzanie do Elasticsearch.

Okresowość

Teraz aktualizacje są konfigurowane na podstawie zdarzeń, zgodnie z następującymi warunkami:

  1. Punkty sprzedaży. Gdy tylko otrzymamy dane z zewnętrznego źródła, od razu przystępujemy do aktualizacji.
  2. Aktualności. Gdy tylko jakiekolwiek wiadomości zostaną zredagowane na stronie, są automatycznie wysyłane do Elastic.

Tutaj ponownie warto wspomnieć o zaletach Elastic. W Postgresie, wysyłając żądanie, musisz poczekać, aż rzetelnie przetworzy wszystkie rekordy. Możesz wysłać 10 XNUMX rekordów do Elastic i natychmiast rozpocząć pracę, nie czekając na dystrybucję rekordów do wszystkich Shardów. Oczywiście niektóre odłamki lub repliki mogą nie widzieć danych od razu, ale wszystko będzie dostępne już wkrótce.

Metody integracji

Istnieją 2 sposoby integracji z Elastic:

  1. Przez natywnego klienta przez TCP. Natywny sterownik stopniowo wymiera: nie jest już wspierany, ma bardzo niewygodną składnię. Dlatego praktycznie go nie używamy i staramy się całkowicie z niego zrezygnować.
  2. Poprzez interfejs HTTP, który może wykorzystywać zarówno żądania JSON, jak i składnię Lucene. Ostatni to silnik tekstowy wykorzystujący Elastic. W tej wersji otrzymujemy możliwość Batchowania poprzez żądania JSON przez HTTP. To jest opcja, której próbujemy użyć.

Dzięki interfejsowi HTTP możemy korzystać z bibliotek zapewniających asynchroniczną implementację klienta HTTP. Możemy skorzystać z Batcha i asynchronicznego API, co przekłada się na wysoką wydajność, co bardzo pomogło w czasach wielkiej promocji (więcej o tym poniżej)

Kilka liczb dla porównania:

  • Zapisywanie użytkowników nagród Postgres w 20 wątkach bez grupowania: 460713 rekordów w 42 sekundy
  • Elastic + klient reaktywny na 10 wątków + wsad na 1000 elementów: 596749 rekordów w 11 sekund
  • Elastic + klient reaktywny na 10 wątków + wsad na 1000 elementów: 23801684 wpisów w 4 minuty

Teraz napisaliśmy menedżera żądań HTTP, który buduje JSON jako Batch / nie Batch i wysyła go przez dowolnego klienta HTTP, niezależnie od biblioteki. Możesz także wybrać wysyłanie żądań synchronicznie lub asynchronicznie.

W niektórych integracjach nadal korzystamy z oficjalnego klienta transportowego, ale to już tylko kwestia kolejnego refaktoryzacji. W tym przypadku do przetwarzania wykorzystywany jest niestandardowy klient zbudowany w oparciu o Spring WebClient.

Optymalizacja obciążenia w projekcie Highload za pomocą ElasticSearch

duża promocja

Raz w roku projekt organizuje dużą promocję dla użytkowników - to ten sam Highload, ponieważ w tym czasie pracujemy z dziesiątkami milionów użytkowników jednocześnie.

Zwykle szczyty obciążeń występują w okresie wakacyjnym, ale ta promocja jest na zupełnie innym poziomie. Przed rokiem w dniu promocji sprzedaliśmy 27 580 890 sztuk towaru. Dane były przetwarzane przez ponad pół godziny, co spowodowało niedogodności dla użytkowników. Użytkownicy otrzymywali nagrody za udział, ale stało się jasne, że trzeba przyspieszyć ten proces.

Na początku 2019 roku zdecydowaliśmy, że potrzebujemy ElasticSearch. Przez cały rok organizowaliśmy przetwarzanie otrzymanych danych w Elastic i ich wydawanie w api aplikacji mobilnej i serwisu. W rezultacie w następnym roku podczas kampanii przetworzyliśmy 15 131 783 wpisów w 6 minut.

Ponieważ mamy dużo osób, które chcą kupić towar i wziąć udział w losowaniu nagród w promocjach, jest to środek tymczasowy. Teraz wysyłamy aktualne informacje do Elastic, ale w przyszłości planujemy przenieść zarchiwizowane informacje z ostatnich miesięcy do Postgres jako trwałe miejsce. Aby nie zapchać indeksu Elastic, który też ma swoje ograniczenia.

Wnioski/Wnioski

W tej chwili przenieśliśmy wszystkie usługi, które chcieliśmy do Elastic i na razie wstrzymaliśmy się z tym. Teraz budujemy indeks w Elastic na szczycie głównego trwałego magazynu w Postgres, który przejmuje obciążenie użytkowników.

W przyszłości planujemy przenieść usługi, jeśli uznamy, że żądanie danych staje się zbyt zróżnicowane i jest przeszukiwane pod nieograniczoną liczbę kolumn. To już nie jest zadanie dla Postgres.

Jeśli potrzebujemy wyszukiwania pełnotekstowego w funkcjonalności lub jeśli mamy wiele różnych kryteriów wyszukiwania, to już wiemy, że trzeba to przetłumaczyć na Elastic.

⌘⌘⌘

Dziękuje za przeczytanie. Jeśli Twoja firma również korzysta z ElasticSearch i ma własne przypadki wdrożeniowe, powiedz nam o tym. Ciekawie będzie wiedzieć, jak inni 🙂

Źródło: www.habr.com

Dodaj komentarz