KeyDB jako [potencjalna] alternatywa dla Redis

Na Habrze nie znaleziono recenzji „szybszej alternatywy dla Redis” — KeyDB. Zdobywając wystarczająco świeże doświadczenie w jego użyciu, chcemy wypełnić tę lukę.

KeyDB jako [potencjalna] alternatywa dla Redis

Historia jest dość banalna: pewnego dnia, przy dużym napływie ruchu, zaobserwowano znaczną degradację wydajności aplikacji (a konkretnie — czasu odpowiedzi). W tamtym czasie, niestety, nie udało się przeprowadzić normalnej diagnostyki tego, co się dzieje, dlatego później zaplanowano szereg testów obciążeniowych. Po ich przeprowadzeniu udało się zidentyfikować wąskie gardło, którym okazało się buforowanie bazy danych w Redis. Jak to często bywa, problemu nie można było rozwiązać od razu — zespołowi programistycznemu (zmiana logiki działania). Dlatego pojawiła się ciekawość i chęć rozwiązania sytuacji okrężną drogą. I tak powstał ten artykuł.

Problematyka

O Redisie w ogóle

Jak wiadomo, Redis jest bazą danych działającą w trybie jednowątkowym. Mówiąc ściślej, jest taki w kontekście pracy z danymi użytkowników. Od czwartej wersji operacje wewnętrzne Redis przetłumaczone są wykonywane równolegle. Niemniej jednak, ta zmiana dotyczyła jedynie niewielkiej części obciążenia, ponieważ główna praca koncentruje się na danych użytkowników.

Na ten temat napisano niezliczone ilości artykułów, ale programiści Redis uporczywie nie chcą wprowadzać pełnej równoległości, podkreślając, jak bardzo skomplikuje to aplikację i zwiększy koszty eksploatacji, a także wprowadzi więcej błędów. Ich stanowisko jest takie: jeśli napotkałeś problem jednego rdzenia – masz problemy z architekturą aplikacji i musisz coś w niej zmienić. Wśród użytkowników, jednak, jest również „drugi oboz” — tych, którzy utknęli przy jednym rdzeniu i twierdzą, że Redis sami tworzą wąskie gardło. W przypadku naprawdę dużych obciążeń – prędzej czy później – nieuchronnie napotkasz ten problem, co nakłada znaczne ograniczenia na architekturę i/lub zmusza do jej komplikacji.

Nie będę oceniać żadnego z tych poglądów. Zamiast tego podzielę się naszym konkretnym przypadkiem i tym, jak go rozwiązaliśmy.

Nasz przypadek

W jednym z projektów natrafiliśmy na problem, że zespół deweloperski skonfigurował niezwykle agresywne buforowanie danych z bazy danych (PostgreSQL) poprzez Redis. Był to jedyny sposób, który podczas nagłych wzrostów ruchu ratował samą PostgreSQL i, w konsekwencji, aplikację.

Po serii testów obciążeniowych przeprowadziliśmy analizę sytuacji i odkryliśmy, że Redis ograniczał się do jednego rdzenia (co nazywa się „w polu”), po czym nastąpiła dość szybka degradacja aplikacji. „Dławienie” miało postać postępu geometrycznego: jak tylko osiągnięto limit wydajności Redis, wszystko przestawało działać.

Wyglądało to mniej więcej tak:

KeyDB jako [potencjalna] alternatywa dla Redis

Ze strony New Relic jednoznacznie zidentyfikowano problem:

KeyDB jako [potencjalna] alternatywa dla Redis

A oto statystyki operacji get w Redis:

KeyDB jako [potencjalna] alternatywa dla Redis

Po tym, jak problem został szczegółowo przedstawiony zespołowi deweloperskiemu, okazało się, że "jest niemożliwe, aby teraz rozwiązać problem". Tak rozpoczęły się poszukiwania rozwiązania ze strony operacyjnej, a odpowiedzią było wspomniane już KeyDB.

Jednak zanim przejdziemy do jego przeglądu, warto wspomnieć, że w projekcie używany jest niezależny Redis, ponieważ klastrowe rozwiązanie oparte na Sentinel ma znacznie wyższe opóźnienia. Jednym z oczywistych rozwiązań było stworzenie kilku replik bufora: niech aplikacja łata się wszędzie z równoważeniem! Jednak po konsultacjach z deweloperami byliśmy zmuszeni odrzucić tę opcję z powodu aktywnego i skomplikowanego mechanizmu unieważniania bufora w aplikacji. Ten sam problem dotyczył także shardowania bufora.

Szybki przegląd KeyDB

W poszukiwaniu możliwego rozwiązania problemu odkryliśmy aplikację o nazwie KeyDB. To fork Redis, opracowany przez kanadyjską firmę i dystrybuowany na licencji BSD. Projekt jest stosunkowo młody: istnieje od początku 2019 roku. Historia jest taka, że autorzy również pewnego dnia napotkali ograniczenia Redis… i postanowili stworzyć swój fork. Co więcej, nie tylko rozwiązał znane problemy, ale również uzyskał dodatkowe możliwości, które dostępne są tylko w wersji enterprise Redis.

Dla tych, którzy chcą dokładniej zapoznać się z KeyDB, istnieje dobry artykuł wprowadzający na Medium, który przedstawia bazę danych oraz krótki benchmark porównujący ją z jej „rodzicem” — Redis.

Przede wszystkim przyciągnęło nas w KeyDB potencjalne rozwiązanie naszych problemów, a także interesowały nas pewne dodatkowe funkcje. Użycie KeyDB obiecywało następujące zalety:

  • uzyskanie pełnoprawnej wielowątkowości;
  • pełna i absolutna zgodność z Redis (dla nas to było szczególnie ważne, ponieważ żadne zmiany w aplikacji nie były możliwe), co również obiecywało bezproblemową migrację;
  • wbudowany mechanizm kopii zapasowej w magazynie S3;
  • łatwa do wdrożenia replikacja aktywna;
  • prosta klasteryzacja i sharding bez Sentinel i innego oprogramowania pomocniczego.

Ponad 3 tysiące gwiazdek i wielu współtwórców na GitHubie również wyglądały obiecująco. Aplikacja jest Dość aktywnie rozwijana i wspierana, co widać po commitach, komunikacji w issues, a także zamkniętych (zaakceptowanych) PR. Odpowiedzi od głównego maintainer'a są zawsze przyjazne i szybkie. Ogólnie rzecz biorąc, argumentów było pod dostatkiem.

Migracja i wyniki

Nawet mimo, że projekt migracji był swoistą przygodą (ze względu na nowość KeyDB), nie było zbyt wiele do stracenia. W końcu można było szybko i łatwo cofnąć zmiany — na szczęście cała infra struktura była wdrożona w Kubernetes, a wbudowane mechanizmy Rolling Update doskonale radziły sobie z takimi zadaniami.

Ogólnie przygotowaliśmy szablony Helm, przełączyliśmy aplikację w środowisku testowym na nową bazę danych i wdrożyliśmy to wszystko, oddając do działu QA klienta.

Rozpoczęły się testy, które trwały około tygodnia i nie zagłębialiśmy się w szczegóły. Wiemy tylko, że klient sprawdził standardowe funkcje pracy z Redis za pomocą sterownika PHP phpredis, a także przeprowadził testy QA interfejsu użytkownika. Po tym otrzymaliśmy zielone światło: nie odkryto żadnych skutków ubocznych przy korzystaniu z nowego oprogramowania. To znaczy, z perspektywy aplikacji w ogóle nic się nie zmieniło.

Warto zauważyć, że w konfiguracji też nic nie zmienialiśmy: dosłownie — po prostu wymieniliśmy używany obraz. To samo dotyczy monitorowania i eksportowania metryk do Prometheusa: najczęściej używany z nich doskonale działa z KeyDB i bez jakichkolwiek modyfikacji. W ten sposób można śmiało powiedzieć, że z perspektywy eksploatacji to po prostu idealne przeniesienie.

Dzięki temu, po przełączeniu aplikacji na nową bazę danych, nie można nic zmieniać, a jako „środek stabilizacyjny” można zostawić ją w takim stanie do pracy w produkcji przez jakiś czas. Jednak, jeśli chcesz zobaczyć wzrost wydajności (lub w ogóle jakiekolwiek zmiany), musisz pamiętać, że domyślnie parametr KeyDB, odpowiedzialny za wielowątkowość (server-threads), wynosi jeden, czyli baza danych działa dokładnie tak samo jak Redis.

Po przełączeniu, testach i pewnym czasie życia na nowej aplikacji (z KeyDB) postanowiliśmy powtórzyć test obciążeniowy z tymi samymi parametrami, które stosowano dla Redis. Jakie były jego wyniki?..

Na wykresie wykorzystania CPU od razu widać usunięcie problemów z „sufitem” na jednym rdzeniu: proces zaczął korzystać z dostępnych zasobów:

KeyDB jako [potencjalna] alternatywa dla Redis

A potem próbowałem dość mocno „męczyć” aplikację i zauważyłem zużycie sięgające trzech rdzeni…

Według danych z New Relic, aplikacja webowa zachowywała się znacznie lepiej przy takiej samej obciążeniu. Pewna degradacja wydajności była nadal obserwowana, jednak porównując z analogicznym wykresem powyżej, możesz sam ocenić znaczący postęp:

KeyDB jako [potencjalna] alternatywa dla Redis

Wskaźnik opóźnienia w nowej bazie danych (KeyDB) również się pogorszył, jednak pozostawał w dopuszczalnych wartościach:

KeyDB jako [potencjalna] alternatywa dla Redis

Na następnym wykresie dobrze widać, że liczba zapytań do samego KeyDB jest podobna:

KeyDB jako [potencjalna] alternatywa dla Redis

Podsumowując te syntetyczne testy, można powiedzieć, że zarówno Redis, jak i KeyDB pokazują znaczną degradację wydajności w opóźnieniach (40 ms+) przy znacznym wzroście liczby równoległych połączeń (1000+). W naszym przypadku aplikacji webowej udało się „zredukować” opóźnienie Redis’a przy mniejszej liczbie połączeń (400+), chociaż dla KeyDB takie obciążenie pozostawało akceptowalne.

Wnioski

Ten przykład doskonale ukazuje siłę społeczności Open Source w rozwoju projektów, którymi się interesuje. W sieci natknąłem się na świetne stwierdzenie, które można streścić w następujący sposób: „Jakaś duża firma tworzy ciekawy produkt, udostępnia część jego funkcji za darmo, ale najważniejsza część pozostaje płatna. Społeczność korzysta, korzysta, a potem ktoś macha ręką i robi fork, realizując w nim te płatne funkcje i udostępniając je wszystkim”. Oto KeyDB — to właśnie ten przypadek.

Jeśli chodzi o samą migrację, która przebiegła zaskakująco sprawnie, nie otrzymaliśmy tak znaczącego wzrostu wydajności, jakiego można by oczekiwać, patrząc na wykresy autorów KeyDB… Jednak to tylko nasz indywidualny przypadek, w którym może być wiele odchyleń dotyczących również kontrowersyjnej architektury aplikacji (na przykład ogromna liczba komend get w Redis zamiast bardziej wydajnej wersji agregowanych zapytań mget…). Niemniej jednak, osiągnęliśmy pozytywne wyniki, a wraz z nimi wiele użytecznych funkcji, które będziemy wdrażać w najbliższym czasie.

Ogólnie, KeyDB wygląda obiecująco: w miarę zdobywania praktycznego doświadczenia z tym systemem zarządzania bazami danych (a jeszcze tylko musimy je zdobyć!) oraz rozwoju samego projektu rozważymy możliwość jego zastosowania w innych sytuacjach.

Jednak nie należy traktować tego artykułu jako przewodnika (a tym bardziej — wezwania) do powszechnego porzucenia Redis na rzecz KeyDB. Pomimo naszego pozytywnego doświadczenia, oczywiście nie jest to srebrna kula. Sytuacja była dość specyficzna: konkretnie dla rozwiązania pilnego problemu w sytuacji, gdy potrzeba było działać szybko i przy minimalnych kosztach, takie rozwiązanie się sprawdziło. Czy KeyDB będzie przydatne w Twoim przypadku? Przynajmniej teraz wiesz, że taka potencjalna możliwość istnieje.

P.S.

Przeczytaj także na naszym blogu:

Ź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