Na Habr nie było żadnych recenzji „szybszej alternatywy dla Redis” — Mając całkiem nowe doświadczenie w jego stosowaniu, chciałbym wypełnić tę lukę.
![KeyDB jako [potencjalny] zamiennik Redis](/wp-content/uploads/2020/02/9642ef3dc712ad2e6304104facb464b7.jpeg)
Tło jest dość trywialne: kiedyś, przy dużym napływie ruchu, odnotowano znaczną degradację wydajności aplikacji (mianowicie czasu reakcji). Wtedy niestety nie było możliwe przeprowadzenie normalnej diagnozy tego, co się dzieje, więc zaplanowano serię testów obciążeniowych. Po ich przeprowadzeniu udało się wykryć wąskie gardło, jakim była pamięć podręczna bazy danych w Redis. Jak to często bywa, problemu nie udało się rozwiązać od razu i we właściwy sposób - przez programistów (poprzez zmianę logiki pracy). Dlatego też włączyła się ciekawość i chęć wyjścia z sytuacji okrężną drogą. Tak powstał ten artykuł.
Problemy
O Redisie ogólnie
Jak wiele osób wie, Redis jest bazą danych jednowątkową. Mówiąc dokładniej, jest tak w kontekście pracy z danymi użytkownika. W końcu od czwartej wersji usługa, wewnętrzne operacje Redis do równoległego wykonywania. Jednak ta zmiana dotyczyła tylko niewielkiej części obciążenia, ponieważ większość pracy jest wykonywana na danych użytkownika.
Istnieje niezliczona ilość lanc złamanych na ten temat, ale twórcy Redis uparcie nie chcą implementować pełnego paralelizmu, wspominając, jak bardzo skomplikuje to aplikację i zwiększy koszty ogólne, a także doda szereg błędów. Ich stanowisko jest następujące: jeśli napotkasz problem jednordzeniowy, masz problemy z architekturą aplikacji i coś w niej trzeba zmienić. Wśród użytkowników jest jednak również „inny obóz” – tych, którzy tkwią w jednym rdzeniu i twierdzą, że Redis tworzy dla siebie wąskie gardło. W przypadku naprawdę dużych obciążeń – prędzej czy później – zderzenie z tym problemem jest nieuniknione, co nakłada znaczne ograniczenia na architekturę i/lub wymusza w niej komplikacje.
Nie będę oceniać tej czy innej opinii. Zamiast tego podzielę się naszym konkretnym przypadkiem i tym, jak go rozwiązaliśmy.
Nasz przypadek
W jednym z projektów napotkaliśmy fakt, że zespół programistów skonfigurował niezwykle agresywne buforowanie danych z bazy danych (PostgreSQL) za pośrednictwem Redis. Był to jedyny sposób, który uratował samego PostgreSQL, a w efekcie aplikację przed śmiercią podczas nagłych wzrostów ruchu.
Po serii testów obciążeniowych przeanalizowaliśmy sytuację i odkryliśmy, że Redis był ograniczony do jednego rdzenia (tzw. „the shelf”), po czym aplikacja dość szybko się degradowała. „Dławienie” miało geometryczny przebieg: gdy tylko Redis osiągnął limit wydajności, wszystko przestawało działać.
Wyglądało to mniej więcej tak:
![KeyDB jako [potencjalny] zamiennik Redis](/wp-content/uploads/2020/02/c0f55ca1d9f28f8c305bb74cdc77a84a.jpeg)
New Relic wyraźnie zidentyfikowało problem:
![KeyDB jako [potencjalny] zamiennik Redis](/wp-content/uploads/2020/02/ce72e290f84560d143f2d6c128358477.jpeg)
A oto statystyki operacji get w Redis:
![KeyDB jako [potencjalny] zamiennik Redis](/wp-content/uploads/2020/02/31d98a6bb2985cfbe391976e24b8a8a6.jpeg)
Po szczegółowym zgłoszeniu problemu do działu rozwoju okazało się, że „problemu nie da się rozwiązać w tej chwili”. Rozpoczęto więc poszukiwania rozwiązania po stronie operacyjnej, a odpowiedzią był wspomniany już KeyDB.
Jednak zanim zaczniemy go omawiać, warto wspomnieć, że projekt korzysta z samodzielnego Redis, ponieważ rozwiązanie klastrowe oparte na Sentinel jest znacznie gorsze pod względem opóźnienia. Jednym z oczywistych rozwiązań było utworzenie kilku replik pamięci podręcznej: i pozwolenie aplikacji na działanie wszędzie z równoważeniem! Jednak po konsultacjach z programistami byliśmy zmuszeni odrzucić tę opcję ze względu na aktywny i złożony mechanizm unieważniania pamięci podręcznej w aplikacji. Ten sam problem rozciągnął się na fragmentację pamięci podręcznej.
Krótki przegląd KeyDB
W poszukiwaniu możliwego rozwiązania problemu odkryliśmy . Jest to fork Redis opracowany przez i rozpowszechniany na wolnej licencji BSD. Projekt jest dość młody: istnieje od początku 2019 roku. Jego historia jest taka, że autorzy również kiedyś napotkali ograniczenia Redisa... i postanowili zrobić własny fork. Co więcej, nie tylko rozwiązał on znane problemy, ale także otrzymał dodatkowe funkcje, które są dostępne tylko w wersji korporacyjnej Redisa.
Dla tych, którzy chcą dowiedzieć się więcej o KeyDB, istnieje dobry , w którym zaprezentowano system DBMS oraz krótkie testy porównawcze z jego „matką” — Redis.
Przede wszystkim, przyciągnęło nas do KeyDB potencjalne rozwiązanie naszych problemów, a jednocześnie byliśmy zainteresowani dodatkowymi funkcjami. Korzystanie z KeyDB obiecało następujące korzyści:
- uzyskanie pełnej wielowątkowości;
- pełna i absolutna zgodność z Redis (było to dla nas szczególnie ważne, gdyż nie było możliwości wprowadzania jakichkolwiek modyfikacji w aplikacji), co gwarantowało również bezproblemową migrację;
- wbudowany mechanizm tworzenia kopii zapasowej w magazynie S3;
- łatwa do wdrożenia aktywna replikacja;
- proste klastrowanie i partycjonowanie bez użycia Sentinel i innego oprogramowania pomocniczego.
Ponad 3 tysiące gwiazdek i wielu współpracowników na GitHub również wygląda zachęcająco. Aplikacja jest aktywnie rozwijana i wspierana, co jest wyraźnie widoczne w zatwierdzeniach, komunikacji w problemach i zamkniętych (zaakceptowanych) PR-ach. Odpowiedź głównego opiekuna na wszystkich frontach jest zawsze przyjazna i szybka. Generalnie było mnóstwo argumentów.
Migracja i wyniki
Mimo że projekt migracji był trochę ryzykowny (ze względu na nowość KeyDB), nie było nic do stracenia. W końcu cofanie zmian jest dość szybkie i łatwe — na szczęście cała infrastruktura jest wdrożona w Kubernetes, a wbudowane mechanizmy rozwiązać takie problemy idealnie.
Ogólnie rzecz biorąc, przygotowaliśmy szablony Helm, przenieśliśmy aplikację w środowisku testowym do nowej bazy danych i wdrożyliśmy wszystko, przekazując działowi zapewnienia jakości klienta.
Rozpoczęły się testy, które trwały około tygodnia i nie wchodziliśmy w szczegóły. Wiemy tylko, że klient testował standardowe funkcje do pracy z Redisem przy użyciu sterownika PHP , a także przeprowadził testy QA interfejsu użytkownika. Po tym dostaliśmy zielone światło: nie stwierdzono żadnych skutków ubocznych podczas korzystania z nowego oprogramowania. To znaczy, z punktu widzenia aplikacji nic się nie zmieniło.
Warto zauważyć, że nie zmieniliśmy niczego w konfiguracji: dosłownie, po prostu zastąpiliśmy używany obraz. To samo dotyczy monitorowania i eksportowania metryk do Prometheusa: działa świetnie z KeyDB i bez żadnych modyfikacji. Można więc śmiało powiedzieć, że z punktu widzenia operacyjnego jest to po prostu idealny ruch.
Dzięki temu wszystkiemu, po przełączeniu aplikacji na nowy DBMS, możesz zostawić ją taką, jaka jest i przez jakiś czas pracować w bitwie jako „środek stabilizacyjny”. Jeśli jednak chcesz zobaczyć wzrost wydajności (lub jakiekolwiek zmiany), nie powinieneś zapominać, że domyślnie Parametr KeyDB odpowiedzialny za wielowątkowość (server-threads), jest równe jeden, czyli DBMS działa dokładnie tak samo jak Redis.
Po przełączeniu, przetestowaniu i użytkowaniu nowej aplikacji (z KeyDB) przez jakiś czas, postanowiliśmy powtórzyć testowanie obciążenia z tymi samymi parametrami co dla Redis. Jakie były wyniki?..
Wykres wykorzystania procesora natychmiast pokazał, że problemy z „sufitem” jednego rdzenia zostały wyeliminowane: proces zaczął wykorzystywać dostępne zasoby:
![KeyDB jako [potencjalny] zamiennik Redis](/wp-content/uploads/2020/02/8a3a168507ef75a8e1cdf69e1d30d996.jpeg)
Później próbowałem dość mocno „pomęczyć” aplikację i widziałem zużycie nawet trzech rdzeni…
Według New Relic, aplikacja internetowa jako całość, przy tym samym obciążeniu, zaczęła zachowywać się zauważalnie bardziej adekwatnie. Nadal obserwowano pewne pogorszenie wydajności, ale porównując z podobnym wykresem powyżej, możesz sam ocenić znaczący postęp:
![KeyDB jako [potencjalny] zamiennik Redis](/wp-content/uploads/2020/02/f46bf41bd6b8d190f5117d049ed2dce5.jpeg)
Opóźnienie nowej bazy danych (KeyDB) również uległo pogorszeniu, ale pozostało w akceptowalnych granicach:
![KeyDB jako [potencjalny] zamiennik Redis](/wp-content/uploads/2020/02/b9e0a3103a51707628a9f500dfdd53ad.jpeg)
Poniższy wykres wyraźnie pokazuje, że liczba żądań do samego KeyDB jest podobna:
![KeyDB jako [potencjalny] zamiennik Redis](/wp-content/uploads/2020/02/0a067239194adb39eb3c3738fa73860e.jpeg)
Podsumowując te testy syntetyczne, możemy powiedzieć, że zarówno Redis, jak i KeyDB wykazują znaczną degradację wydajności w zakresie latencji (40 ms+) przy znacznym wzroście liczby połączeń równoległych (1000+). W naszym przypadku aplikacja internetowa zdołała „obniżyć” latencję Redis nawet przy mniejszej liczbie połączeń (400+), chociaż dla KeyDB takie obciążenie pozostało akceptowalne.
odkrycia
Ten przykład wyraźnie pokazuje siłę społeczności Open Source w kwestiach rozwijania projektów, którymi jest zainteresowana. Natrafiłem na świetne stwierdzenie w Internecie, którego ogólny sens był następujący: „Jakaś duża firma tworzy interesujący produkt, udostępnia niektóre z jego funkcji, ale pozostawia najważniejszą część płatną. Społeczność używa go i używa, a potem ktoś się poddaje i tworzy forka, implementując w nim te same płatne funkcje i udostępniając je wszystkim”. KeyDB jest właśnie takim przypadkiem.
Mówiąc o samej migracji, która była zaskakująco prosta, nie otrzymaliśmy tak bardzo znaczny wzrost wydajności, czego można się spodziewać, patrząc na wykresy autorów KeyDB... Jest to jednak tylko nasz konkretny przypadek, w którym może być wiele odchyleń, w tym związanych z niesławną architekturą aplikacji (np. ogromna liczba poleceń get w Redis zamiast bardziej wydajnej opcji zapytania agregującego mget…). Mimo wszystko udało nam się osiągnąć pozytywne rezultaty, a wraz z nimi wiele przydatnych funkcji, które wdrożymy dopiero w niedalekiej przyszłości.
Ogólnie rzecz biorąc, KeyDB wygląda obiecująco. W miarę zdobywania praktycznego doświadczenia z tym systemem DBMS (a mamy go jeszcze sporo do zdobycia!) i rozwoju samego projektu, rozważymy możliwość wykorzystania go w innych sytuacjach.
Jednak ten artykuł nie powinien być traktowany jako przewodnik (a tym bardziej wezwanie) do działania, aby porzucić Redis na rzecz KeyDB wszędzie. Pomimo naszych pozytywnych doświadczeń, oczywiste jest, że nie jest to panaceum. Przypadek był bardzo konkretny: konkretnie w celu rozwiązania natychmiastowego problemu w sytuacji, gdy konieczne było zrobienie tego szybko i przy minimalnych kosztach, to rozwiązanie się sprawdziło. Czy KeyDB będzie przydatny w Twoim przypadku? Przynajmniej teraz wiesz, że taka potencjalna okazja istnieje.
PS
Przeczytaj także na naszym blogu:
- «";
- «";
- «";
- «".
Źródło: www.habr.com
