Jak wybieraliśmy system cache w Sportmasterze. Część 1

Cześć! Nazywam się Aleksiej Pjanow, jestem programistą w firmie Sportmaster. W tym poście opowiem, jak zaczęła się praca nad stroną Sportmastera w 2012 roku, jakie inicjatywy udało się "przepchnąć", a jakie problemy napotkaliśmy.

Dziś chcę podzielić się myślami, które wynikają z innego tematu – wybór systemu cache dla backendu java w panelu administracyjnym strony. Ten temat ma dla mnie szczególne znaczenie – choć historia rozwijała się tylko przez 2 miesiące, to w ciągu tych 60 dni pracowaliśmy po 12-16 godzin bez ani jednego dnia wolnego. Nigdy wcześniej nie myślałem i nie wyobrażałem sobie, że można tak dużo pracować.

Dlatego tekst dzielę na 2 części, aby nie przeciążyć odbiorcy. Przeciwnie, pierwsza część będzie bardzo lekka — wprowadzeniem, kilkoma przemyśleniami, czym jest cache. Jeśli jesteś już doświadczonym programistą lub pracowałeś z cache, to z technicznego punktu widzenia w tym artykule prawdopodobnie nie znajdziesz nic nowego. Natomiast dla juniora to krótka przegląd może zasugerować, w którą stronę warto spojrzeć, gdy stanie na takim rozdrożu.

Jak wybieraliśmy system cache w Sportmasterze. Część 1

Gdy nowa wersja strony Sportmaster została uruchomiona w produkcji, dane były pozyskiwane w sposób, delikatnie mówiąc, niewygodny. Podstawą były tabele przygotowane dla poprzedniej wersji strony (Bitrix), które trzeba było załadować do ETL, przekształcić do nowej formy i wzbogacić różnymi elementami z jeszcze dziesięciu systemów. Aby nowy obrazek lub opis produktu znalazły się na stronie, trzeba było czekać do następnego dnia — aktualizacja tylko w nocy, raz dziennie.

Na początku było tak wiele zmartwień w pierwszych tygodniach po premierze, że problemy z obsługą treści były drobnostką. Jednak gdy wszystko się ustabilizowało, rozwój projektu poszedł do przodu — po kilku miesiącach, na początku 2015 roku zaczęliśmy intensywnie rozwijać panel administracyjny. W latach 2015 i 2016 wszystko szło dobrze, regularnie wydawaliśmy aktualizacje, panel admina obejmował coraz większą część przygotowania danych, a my przygotowywaliśmy się na to, że wkrótce nasz zespół dostanie do zaufania najważniejszy i najtrudniejszy element – obrót towarami (pełne przygotowanie i zarządzanie danymi wszystkich produktów). Ale latem 2017 roku, tuż przed uruchomieniem obrotu towarami, projekt znalazł się w bardzo trudnej sytuacji – właśnie z powodu problemów z buforowaniem. O tym epizodzie chcę opowiedzieć w drugiej części tej dwuczęściowej publikacji.

Ale w tym poście zacznę od początku, podsumuję niektóre myśli – wyobrażenia o buforowaniu, które przemyślenie przed dużym projektem byłoby dobrym krokiem.

Kiedy pojawia się zadanie buforowania

Zadanie buforowania nie pojawia się ot tak. Jesteśmy programistami, piszemy produkty oprogramowania i chcemy, aby były pożądane. Jeśli produkt jest pożądany i odnosi sukces — użytkownicy przybywają. A przybywają, i jeszcze przybywają. I oto mamy bardzo wielu użytkowników, a produkt staje się wysoko obciążony.

Na początkowych etapach nie myślimy o optymalizacji i wydajności kodu. Najważniejsza jest funkcjonalność, szybko wdrażamy wer­sy pilotażowe i testujemy hipotezy. A jeśli obciążenie rośnie – podkręcamy sprzęt. Zwiększamy go razy dwa, trzy, pięć, powiedzmy dziesięć. Tutaj finanse przestają pozwalać. A o ile wzrośnie liczba użytkowników? To już nie będą 2-5-10, ale w przypadku sukcesu – to będzie od 100-1000 aż do 100 tysięcy razy. Tak więc prędzej czy później, ale zajmie się tym optymalizacją.

Załóżmy, że jakaś część kodu (nazwijmy tę część funkcją) działa wyjątkowo długo, a my chcemy skrócić czas wykonania. Funkcja – to może być dostęp do bazy danych lub wykonanie jakiejś skomplikowanej logiki – głównie to, co trwa długo. O ile można skrócić czas wykonania? Teoretycznie można to skrócić do zera, ale nie dalej. A jak można skrócić czas wykonania do zera? Odpowiedź: całkowicie wykluczyć wykonanie. Zamiast tego – od razu zwrócić wynik. A jak poznać wynik? Odpowiedź: albo obliczyć, albo gdzieś podejrzeć. Obliczenie — to długo trwa. A podejrzenie — to na przykład zapamiętanie wyniku, który funkcja zwróciła poprzednio przy takich samych parametrach.

To znaczy, realizacja funkcji nie ma dla nas znaczenia. Wystarczy tylko wiedzieć, od jakich parametrów zależy wynik. Wtedy, jeśli wartości parametrów przedstawimy w formie obiektu, który można wykorzystać jako klucz w pewnym magazynie — to wynik obliczenia możemy zapisać i przy następnym zapytaniu odczytać. Jeśli zapis-odczyt wyniku przebiega szybciej niż wykonanie funkcji – mamy zysk na prędkości. Wartość zysku może wynosić nawet 100, 1000, a nawet 100 tysięcy razy (10^5 – to raczej wyjątek, ale w przypadku naprawdę mocno lagującej bazy – jak najbardziej możliwe).

Podstawowe wymagania dla systemu cache'owania

Pierwsze, co może być wymaganiem dla systemu cache'owania — szybki czas odczytu i w nieco mniejszym stopniu – czas zapisu. Tak, ale tylko do momentu, gdy nie wdrażamy systemu na produkcję.

Rozpatrzmy taki przypadek.

Załóżmy, że zapewniliśmy sprzęt do aktualnego obciążenia i teraz stopniowo wprowadzamy cache'owanie. Użytkowników przybywa, obciążenie rośnie – stopniowo dodajemy cache'e, przyłączając je tu i tam. Tak trwa przez pewien czas, a ciężkie funkcje są już prawie nie wywoływane — całe główne obciążenie spoczywa na cache'u. Liczba użytkowników w tym czasie wzrosła N razy.

I jeśli początkowy zapas sprzętu mógł wynosić 2-5 razy, to za pomocą cache'a mogliśmy podnieść wydajność o 10 razy, a w dobrym przypadku o 100, a miejscami nawet o 1000. To znaczy, na tym samym sprzęcie — obsługujemy 100 razy więcej zapytań. Wspaniale, zasłużyliśmy na nagrodę!

Ale teraz, w pewnym pięknym momencie, system przypadkowo zawiódł, a pamięć podręczna upadła. Nic nadzwyczajnego – pamięć podręczna została wybrana z wymaganiem „wysoka prędkość odczytu i zapisu, reszta nie jest ważna”.

Pod względem początkowego obciążenia mieliśmy zapas sprzętowy 2-5 razy, a obciążenie przez ten czas wzrosło 10-100 razy. Dzięki pamięci podręcznej eliminowaliśmy wywołania dla ciężkich funkcji, więc wszystko działało płynnie. A teraz, bez pamięci podręcznej – o ile spadnie nasz system? Co się stanie? System się zawiesi.

Nawet jeśli nasza pamięć podręczna nie upadła, a tylko chwilowo się wyczyściła – trzeba będzie ją podgrzewać, a to zajmie trochę czasu. I w tym czasie główne obciążenie spadnie na funkcjonalność.

Wnioski: wysokoobciążone projekty w produkcji wymagają od systemu pamięci podręcznej nie tylko wysokiej prędkości odczytu i zapisu, ale również integralności danych i odporności na awarie.

Kłopoty z wyborem

W projekcie z panelem administracyjnym wybór przebiegał tak: najpierw zainstalowaliśmy Hazelcast, ponieważ już znaliśmy ten produkt z doświadczenia głównej witryny. Jednak tutaj ten wybór okazał się nietrafiony – przy naszym profilu obciążenia Hazelcast działa nie tylko wolno, ale strasznie wolno. A przed terminami uruchomienia w produkcji już się na to podpisaliśmy.

Spojler: jak dokładnie ułożyły się okoliczności, że przeoczyliśmy taki hicior i znaleźliśmy się w trudnej i napiętej sytuacji – opowiem w drugiej części — oraz jak się znaleźliśmy i jak wyszliśmy. Ale teraz — powiem tylko, że to był duży stres, a „myślenie – jakoś nie myśli się, potrząsamy butelką”. „Potrząsamy butelką” – to też spojler, o tym trochę później.

Co zrobiliśmy:

  1. Sporządzamy listę wszystkich systemów, które wskazuje Google i StackOverflow. Trochę więcej niż 30.
  2. Piszemy testy z obciążeniem charakterystycznym dla produkcji. W tym celu nagraliśmy dane, które przechodzą przez system w środowisku produkcyjnym — taki sniffing danych wewnętrznych systemu. W testach używaliśmy dokładnie tych danych.
  3. Cały zespół, każdy wybiera następny system z listy, konfiguruje, przeprowadza testy. Test nie przechodzi, nie dźwiga obciążenia – wyrzucamy, przechodzimy do następnego w kolejce.
  4. Na 17. systemie stało się jasne, że wszystko jest beznadziejne. Czas przestać „trząść butelką”, pora poważnie się zastanowić.

Jest to opcja, gdy musimy wybrać system, który „przeskoczy” przez wyniki przygotowanych wcześniej testów. A co, jeśli takich testów jeszcze nie ma i chcemy wybrać szybciej?

Modelujmy taką opcję (trudno sobie wyobrazić, że programista na poziomie średnim + żyje w vacuum i w momencie wyboru jeszcze nie zdecydował, jaki produkt wypróbować w pierwszej kolejności – dlatego dalsze rozważania to raczej teoria/filozofia/o juniorze).

Zdefiniowawszy wymagania, zaczniemy wybierać rozwiązanie z pudełka. Po co wymyślać koło na nowo: weźmiemy gotowy system do buforowania.

Jeśli dopiero zaczynasz i będziesz googlować, to kolejność będzie mniej więcej taka, ale ogólnie rzecz biorąc, orientacje będą takie. W pierwszej kolejności natkniesz się na Redis, który jest szeroko znany. Potem dowiesz się, że istnieje EhCache jako najstarszy i sprawdzony system. Dalej będzie mowa o Tarantool – krajowym rozwiązaniu, które ma unikalny aspekt. I również Ignite, ponieważ obecnie jest na fali popularności i ma wsparcie SbierTech. Na końcu jeszcze Hazelcast, ponieważ w świecie enterprise często pojawia się wśród dużych firm.

To nie wyczerpuje listy, istnieje dziesiątki systemów. A my przyczepimy tylko jeden. Weźmiemy wybrane 5 systemów na „konkurs piękności” i przeprowadzimy selekcję. Kto będzie zwycięzcą?

Redis

Czytamy, co piszą na oficjalnej stronie.
Redis — projekt opensource. Oferuje pamięć in-memory, możliwość zapisywania na dysku, automatyczne dzielenie na partycje, wysoką dostępność i odzyskiwanie po przerwach w sieci.

Wygląda na to, że wszystko jest świetnie, można brać i wdrażać – wszystko, co potrzebujesz, robi. Ale zerknijmy z czystej ciekawości na pozostałych kandydatów.

EhCache

EhCache — „najczęściej używany cache dla Javy” (tłumaczone hasło z oficjalnej strony). Również opensource. I tutaj rozumiemy, że Redis nie jest pod javę, jest ogólny, a do współpracy z nim potrzebna jest nakładka. EhCache będzie bardziej wygodne. Co jeszcze obiecuje system? Niezawodność, sprawdzalność, pełna funkcjonalność. No i dodatkowo jest najczęściej stosowane. I buforuje terabajty danych.

Redis został zapomniany, jestem gotów wybrać EhCache.

Ale poczucie patriotyzmu skłania mnie do przyjrzenia się, co dobrego ma Tarantool.

Tarantool

Tarantool — spotyka się z określeniem „Platforma integracji danych w czasie rzeczywistym”. Brzmi to skomplikowanie, więc szczegółowo przeglądamy stronę i znajdujemy głośne stwierdzenie: „Buferuje 100% danych w pamięci operacyjnej”. To powinno budzić wątpliwości — w końcu danych może być znaczenie więcej niż pamięci. Wyjaśnienie jest takie, że tutaj rozumie się, że do zapisu danych na dysku z pamięci Tarantool nie przeprowadza serializacji. Zamiast tego – wykorzystuje niskopoziomowe cechy systemu, kiedy pamięć jest po prostu mapowana na system plików z bardzo dobrymi wskaźnikami I/O. Generalnie, zrobili to w wyjątkowy i świetny sposób.

Przyjrzyjmy się wdrożeniom: Mail.ru, Avito, Beeline, MegaFon, Alfa-Bank, Gazprom…

Jeśli wciąż miałem jakieś wątpliwości co do Tarantoola, to przypadek wdrożenia w Mastercard mnie przekonuje. Biorę Tarantoola.

Ale jednak…

Ignite

… jest jeszcze Ignite, oznaczony jako „platforma obliczeniowa in-memory… prędkość in-memory na petabajtach danych”. Tutaj również jest wiele plusów: rozproszony cache in-memory, najszybsze przechowywanie kluczy i wartości oraz cache, poziome skalowanie, wysoka dostępność, surowa integralność. Generalnie okazuje się, że najszybszy to Ignite.

Wdrożenia: Sberbank, American Airlines, Yahoo! Japan. A potem dowiaduję się, że Ignite nie tylko wdrożono w Sberbanku, ale zespół SberTech wysyła swoich ludzi do zespołu Ignite, aby poprawić produkt. To całkowicie mnie przekonuje i jestem gotów wybrać Ignite.

Całkowicie nie wiadomo po co, patrzę na piąty punkt.

Hazelcast

Wchodzę na stronę Hazelcast, czytam. I okazuje się, że najszybszym rozwiązaniem do rozproszonego cache'owania — jest Hazelcast. Jest znacznie szybszy od wszystkich innych rozwiązań i ogólnie jest liderem w zakresie in-memory data grid. W obliczu tego, aby wziąć coś innego — nie szanować siebie. A ponadto wykorzystuje nadmiarowe przechowywanie danych do ciągłej pracy klastra bez utraty danych.

Wszystko, jestem gotów wziąć Hazelcast.

Porównanie

Jednak jeśli spojrzeć, to wszyscy pięciu kandydaci są tak opisani, że każdy z nich – jest najlepszy. Jak wybrać? Możemy zobaczyć, który z nich jest najpopularniejszy, poszukać porównań, a ból głowy minie.

Znajdujemy taki przegląd, wybieramy nasze 5 systemów.

Jak wybieraliśmy system cache w Sportmasterze. Część 1

Tutaj są posortowane: na górze Redis, na drugim miejscu — Hazelcast, zyskują na popularności Tarantool i Ignite, EhCache jak był, tak pozostał.

Ale przyjrzyjmy się metodzie obliczeniowej: linki do stron internetowych, ogólne zainteresowanie systemem, oferty pracy — super! To znaczy, kiedy mój system przestanie działać, powiem: „Nie, jest niezawodny! A tutaj jest tyle ofert pracy…”. Takie proste porównanie nie jest wystarczające.

Te wszystkie systemy to nie tylko systemy przechowywania w pamięci podręcznej. Mają one znacznie więcej funkcji, w tym – kiedy dane nie są przesyłane do klienta do przetworzenia, ale przeciwnie: kod, który ma być wykonany na danych, przemieszcza się na serwer, tam jest wykonywany, a wynik jest zwracany. Jako oddzielny system do buforowania rzadko jest to rozpatrywane.

Dobrze, nie poddajemy się, znajdziemy bezpośrednie porównanie systemów. Weźmiemy dwa najlepsze warianty — Redis i Hazelcast. Interesuje nas szybkość, pod tym względem je porównamy.

Hz vs Redis

Znajdujemy takie porównanie:
Jak wybieraliśmy system cache w Sportmasterze. Część 1

Niebieski — to Redis, czerwony Hazelcast. Hazelcast wygrywa wszędzie, i to jest uzasadnione: jest wielowątkowy, wysoko zoptymalizowany, każdy wątek pracuje z własną partycją, dlatego nie ma blokad. A Redis — jest jednowątkowy, nie korzysta z nowoczesnych wielordzeniowych CPU. Hazelcast wykorzystuje asynchroniczne I/O, podczas gdy Redis-Jedis — blokujące gniazda. Ostatecznie, Hazelcast używa protokołu binarnego, a Redis jest tekstowy, co oznacza, że jest mniej efektywny.

Na wszelki wypadek zwrócimy się do jeszcze jednego źródła porównania. Co nam pokaże?

Redis vs Hz

Jeszcze jedno porównanie:
Jak wybieraliśmy system cache w Sportmasterze. Część 1

Tutaj z kolei, czerwony — to Redis. To znaczy, Redis wygrywa pod względem wydajności z Hazelcast. W pierwszym porównaniu wygrał Hazelcast, w drugim — Redis. Tutaj bardzo dokładnie wyjaśniono, dlaczego w poprzednim porównaniu wygrał Hazelcast.

Okazuje się, że wynik pierwszego był praktycznie sfałszowany: Redis wzięto z podstawowej wersji, a Hazelcast dostosowano do przypadku testowego. Więc wychodzi na to, że po pierwsze, nikomu nie można ufać, po drugie, gdy już wybierzemy system, musimy go jeszcze właściwie skonfigurować. Te ustawienia obejmują dziesiątki, prawie setki parametrów.

Trzęsienie butelki

Cały proces, który teraz przeszliśmy, mogę wyjaśnić taką metaforą „Trzęsienie butelki”. To znaczy, teraz nie trzeba programować, najważniejsze jest umieć czytać stackoverflow. W moim zespole jest profesjonalista, który dokładnie w taki sposób działa w krytycznych momentach.

Co on robi? Widzi uszkodzony element, dostrzega ślad stosu, wybiera z niego pewne słowa (które to dokładnie — to jego ekspercka wiedza o programie), szuka w Google, znajduje odpowiedzi na Stack Overflow. Nie czytając, nie zagłębiając się — spośród odpowiedzi na pytanie wybiera coś, co najbardziej przypomina zdanie „zrób to i to” (wybranie takiej odpowiedzi to jego talent, bo nie zawsze jest to ten najlepszy odpowiedź, który zebrał najwięcej lajków), stosuje to, sprawdza: jeśli coś się zmieniło, to świetnie. Jeśli nie, cofamy się. I powtarzamy uruchomienie, sprawdzenie, poszukiwanie. W ten intuicyjny sposób osiąga, że po jakimś czasie kod działa. Nie wie dlaczego, nie wie co zrobił, nie potrafi wytłumaczyć. Ale! Ta rzecz działa. I „pożar ugaszony”. Teraz rozkładamy na czynniki to, co zrobiliśmy. Kiedy program działa — to jest o wiele łatwiejsze. I znacznie oszczędza czas.

Ten sposób jest bardzo dobrze wyjaśniony na takim przykładzie.

Kiedyś bardzo popularne było składanie żaglówki w butelce. Żaglówka jest duża i krucha, a szyjka butelki bardzo wąska, nie da się jej w środku włożyć. Jak ją złożyć?

Jak wybieraliśmy system cache w Sportmasterze. Część 1

Jest taka metoda, bardzo szybka i bardzo skuteczna.

Statek składa się z wielu drobiazgów: patyków, sznurków, żagli, kleju. Wszystko to wkładamy do butelki.
Bierzemy butelkę obiema rękami i zaczynamy ją trząść. Tak ją trzęsiemy, trzęsiemy. I zazwyczaj — wychodzi z tego kompletny bałagan, oczywiście. Ale czasami. Czasami wychodzi statek! Dokładniej, coś, co przypomina statek.

Pokazujemy to coś komuś: „Siergiej, widzisz!?”. I rzeczywiście, z daleka — wygląda jak statek. Ale dalej tego nie można puszczać.

Jest jeszcze inny sposób. Używają go bardziej zaawansowani chłopaki, tacy hakerzy.

Dałem takiemu gościowi zadanie, wszystko zrobił i poszedł. I patrzysz — wydaje się, że zrobione. Ale po pewnym czasie, kiedy trzeba poprawić kod — zaczyna się tam takie zamieszanie z jego powodu... Dobrze, że zdążył się daleko oddalić. To tacy chłopaki, którzy na przykładzie butelki zrobią tak: widzicie, tam, gdzie denko — szkło się wygina. I nie do końca wiadomo, czy jest przezroczyste, czy nie. Wtedy „hakerzy” odcinają to denko, wkładają w to statek, a denko potem przyklejają z powrotem, jakby tak miało być.

Z perspektywy postawienia zadania wydaje się, że wszystko jest w porządku. Ale biorąc pod uwagę przykład statków: po co w ogóle zrobić ten statek, komu on tak naprawdę jest potrzebny? Nie ma żadnej funkcjonalności. Zwykle takie statki to prezenty dla bardzo wysoko postawionych osób, które stawiają je na półce nad sobą jako pewien symbol, znak. A jeśli u takiej osoby, szefa dużej firmy lub wysokiego urzędnika, jako flagę będzie stała taka tandeta, której szyjka jest odcięta? Lepiej, żeby nigdy się o tym nie dowiedział. Jak więc właściwie robi się te statki, które można podarować ważnej osobie?

Jedynym miejscem, kluczowym, z którym nie można nic zrobić, jest kadłub. I kadłub statku przechodzi przez szyjkę. Tymczasem statek jest składany poza butelką. Ale to nie jest proste złożenie statku, to prawdziwa rzemieślnicza sztuka. Do części składowych dodawane są specjalne dźwignie, które umożliwiają późniejsze ich podniesienie. Na przykład żagle składają się, są starannie wnoszone do środka, a następnie za pomocą pincety bardzo precyzyjnie są podciągane i unoszone. W rezultacie powstaje dzieło sztuki, które można z czystym sumieniem i dumą podarować.

Jeśli chcemy, aby projekt był udany – w zespole powinien być przynajmniej jedna osoba-jubiler. Taki, który dba o jakość produktu i uwzględnia wszystkie aspekty, nie rezygnując z żadnego, nawet w chwilach stresu, gdy okoliczności wymagają szybkiego działania kosztem ważnych rzeczy. Wszystkie udane projekty, które są stabilne i przetrwały próbę czasu, są oparte na tej zasadzie. Mają w sobie coś bardzo precyzyjnego i unikalnego, coś, co wykorzystuje wszystkie dostępne możliwości. W przykładzie z statkiem w butelce – podkreśla się to, że kadłub statku przechodzi przez szyjkę.

Wracając do zadania wyboru naszego serwera pamięci podręcznej, jak można by zastosować tę metodę? Proponuję taki sposób wyboru spośród wszystkich dostępnych systemów – nie potrząsać butelką, nie wybierać, lecz spojrzeć, co w zasadzie w nich jest, na co zwracać uwagę przy wyborze systemu.

Gdzie szukać wąskiego gardła?

Spróbujemy nie trzymać butelki w ręku, nie przeglądać wszystkiego po kolei, ale zobaczymy, jakie zadania mogą się pojawić, gdybyśmy chcieli zaprojektować taki system samodzielnie. Nie będziemy budować roweru, ale posłużymy się tym schematem, aby zorientować się, na jakie aspekty zwracać uwagę w opisach produktów. Sporządźmy taki schemat.

Jak wybieraliśmy system cache w Sportmasterze. Część 1

Jeśli system jest rozproszony, oznacza to, że będziemy mieć kilka serwerów (6). Załóżmy, że cztery (wygodnie umieścić na obrazku, ale oczywiście może ich być dowolna liczba). Jeśli serwery znajdują się na różnych węzłach, oznacza to, że na wszystkich działa jakiś kod, odpowiadający za to, aby te węzły stworzyły klaster i w przypadku zerwania połączenia - łączyły się i wzajemnie identyfikowały.

Potrzebny jest również kod-logika (2), który odpowiada za pamięć podręczną. Klienci współdziałają z tym kodem za pośrednictwem pewnego API. Kod kliencki (1) może być realizowany w tym samym JVM lub łączyć się z nim przez sieć. Logika wdrożona wewnętrznie to decyzje, które obiekty w pamięci podręcznej pozostawić, a które wyrzucić. Do przechowywania pamięci podręcznej wykorzystujemy pamięć (3), ale jeśli zajdzie taka potrzeba, część danych możemy również zapisać na dysku (4).

Zobaczmy, w których częściach będzie występował obciążenie. Rzeczywiście, obciążone będą każda strzałka i każdy węzeł. Po pierwsze, pomiędzy kodem klienckim a API, jeśli jest to interakcja sieciowa, opóźnienie może być dość zauważalne. Po drugie, w ramach samego API - przesadzając ze złożoną logiką, możemy napotkać ograniczenia procesora. Dobrym pomysłem byłoby, aby logika nie zajmowała pamięci więcej niż to konieczne. Pozostaje jeszcze współpraca z systemem plików - w zwykłym wariancie jest to serializacja / odtworzenie oraz zapis / odczyt.

Następnie interakcja z klastrem. Prawdopodobnie będzie się on znajdował w tym samym systemie, ale może być również oddzielny. Tutaj także należy uwzględnić przesył danych do niego, prędkość serializacji danych oraz interakcję między klastrem.

Teraz, z jednej strony - możemy wyobrazić sobie, "jakie zębatki będą się kręcić" w systemie pamięci podręcznej podczas przetwarzania zapytań z naszego kodu, a z drugiej strony - możemy oszacować, jakie i ile zapytań nasz kod wygeneruje do tego systemu. To wystarczy, aby podjąć bardziej lub mniej rozsądny wybór - dobrać system do naszego przypadku użycia.

Hazelcast

Zobaczmy, jak zastosować takie rozłożenie do naszej listy. Na przykład, Hazelcast.

Aby przechować lub pobrać dane z Hazelcast, kod kliencki zwraca się (1) do api. Hz pozwala uruchomić serwer jako embedded, a w takim przypadku wywołanie do api – to wywołanie metody wewnątrz JVM, można to uznać za bezpłatne.

Aby logika działała w (2), Hz opiera się na haszu od tablicy bajtów zserializowanego klucza – to znaczy, że serializacja klucza odbędzie się w każdym razie. To nieuchronny overhead dla Hz.
Strategie Eviction zostały dobrze zaimplementowane, ale w wyjątkowych przypadkach można podłączać swoje. O tę część nie trzeba się martwić.

Magazyn (4) można podłączać. Świetnie. Interakcja (5) dla embedded można uznać za natychmiastową. Wymiana danych między węzłami w klastrze (6) – tak, istnieje. To wkład w odporność na awarie kosztem prędkości. Zmniejszenie kosztów umożliwia funkcja Hz Near-cache – dane pochodzące z innych węzłów klastra będą buforowane.

Co można zrobić w takich warunkach, aby zwiększyć prędkość?

Na przykład, aby uniknąć serializacji klucza w (2) – należy dodać jeszcze jeden cache nad Hazelcast, dla najbardziej gorących danych. W Sportmasterze do tego celu wybrano Caffeine.

Dla dostosowania na poziomie (6), w Hz zaproponowano dwa typy przechowywania: IMap i ReplicatedMap.
Jak wybieraliśmy system cache w Sportmasterze. Część 1

Warto wspomnieć, jak Hazelcast trafił do staku technologii Sportmaster.

W 2012 roku, gdy pracowaliśmy nad pierwszym prototypem przyszłej strony, to właśnie Hazelcast był pierwszym wynikiem, który wydała wyszukiwarka. Spotkanie rozpoczęło się 'od razu' – zakupili nas tym, że zaledwie po dwóch godzinach, gdy podłączyliśmy Hz do systemu – działał. I działał dobrze. Do końca dnia dopisaliśmy kilka testów, cieszyliśmy się. I tego zapasu energii wystarczyło, by pokonać te niespodzianki, które Hz z czasem podsuwał. Teraz zespół Sportmaster nie ma powodów, by rezygnować z Hazelcast.

Jednak takie argumenty, jak 'pierwszy wynik w wyszukiwarce' i 'szybko zbudowaliśmy HelloWorld' – to oczywiście wyjątek i szczególność momentu, w którym dokonano wyboru. Prawdziwe wyzwania dla wybranego systemu zaczynają się przy wprowadzeniu do produkcji, i na ten etap warto zwrócić uwagę przy wyborze jakiegokolwiek systemu, w tym także cache. Właściwie, w naszym przypadku można powiedzieć, że wybraliśmy Hazelcast przypadkowo, ale potem okazało się, że dokonaliśmy właściwego wyboru.

W produkcji o wiele ważniejsze są: monitorowanie, obsługa awarii na poszczególnych węzłach, replikacja danych, koszty skalowania. Warto zwrócić uwagę na problemy, które mogą wystąpić podczas utrzymania systemu – kiedy obciążenie kilkadziesiąt razy przekroczy planowane, gdy przypadkowo prześlemy coś niewłaściwego i do niewłaściwego miejsca, oraz gdy będzie konieczne wprowadzenie nowej wersji kodu, zastąpienie danych i uczynienie tego niezauważalnym dla klientów.

Hazelcast z pewnością spełnia wszystkie te wymagania.

Ciąg dalszy nastąpi

Jednak Hazelcast nie jest panaceum. W 2017 roku wybraliśmy Hazelcast jako pamięć podręczną w panelu administracyjnym, opierając się jedynie na dobrym wrażeniu z przeszłych doświadczeń. Odegrało to kluczową rolę w bardzo złośliwym żarcie, przez co znaleźliśmy się w trudnej sytuacji i "bohatersko" wychodziliśmy z niej przez 60 dni. Ale o tym w następnej części.

A tymczasem... Szczęśliwego Nowego Kodu!

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster