В Habr не бяха намерени рецензии "по-бързите алтернативи на Redis" — . След като получих достатъчно свеж опит с него, искам да запълня това празно място.
![KeyDB като [потенциална] замяна за Redis.](/wp-content/uploads/2020/02/9642ef3dc712ad2e6304104facb464b7.jpeg)
Предисторията е доста банална: веднъж, при голям трафик, беше забелязано значително влошаване на производителността на приложението (а именно — времето за отговор). По това време, за съжаление, не успяхме да проведем нормална диагностика на случващото се, затова впоследствие плануваме редица тестове с натоварване. След тяхното провеждане успяхме да открием тесния проход, който беше кешът на базата данни в Redis. Както често се случва, не можехме да решим проблема веднага и правилно — чрез усилията на разработчиците (чрез промяна на логиката). Затова се включи любопитството и желанието да се справим със ситуацията, пообикаляйки я. Така се появи тази статия.
Проблематика
За Redis като цяло
Както много хора знаят, Redis е еднопоточна база данни. Ако сме по-точни, тя е такава в контекста на работа с потребителски данни. Всъщност, от четвърта версия, служебните, вътрешните операции на Redis към паралелно изпълнение. Все пак, това изменение засегна само малка част от натоварването, тъй като основната работа е съсредоточена върху потребителските данни.
На тази тема са били разрушени безброй копия, но разработчиците на Redis упорито не искат да внедрят пълна паралелност, споменавайки колко ще усложни приложението и ще увеличи разходите, както и ще добави брой грешки. Тяхната позиция е следната: ако сте се сблъскали с проблема на едноядреност — имате проблем с архитектурата на приложението и трябва нещо да се промени в нея. Между потребителите обаче има и "друг лагер" — от тези, които са се натъкнали на едно ядро и твърдят, че Redis самите себе си създават бутилечно гърло. В случай на наистина големи натоварвания — рано или късно — е неизбежно да се сблъскате с този проблем, което налага значителни ограничения върху архитектурата и/или принудителни усложнения в нея.
Няма да давам оценка на това или онова мнение. Вместо това ще споделя нашия конкретен случай и как го решихме.
Нашият случай
В един от проектите се сблъскахме с проблема, при която екипът за разработка настрои изключително агресивно кеширане на данните от БД (PostgreSQL) чрез Redis. Това беше единственият начин, по който по време на резки търговски натоварвания спасихме самата PostgreSQL и, следователно, приложението.
След серия натоварващи тестове проведохме анализ на ситуацията и открихме, че Redis е натоварен на едно ядро (т.нар. „в полка“), след което последва много бърза деградация на приложението. „Задушаването“ имаше геометрична прогресия: веднага щом се достига границата на производителността на Redis, всичко спираше да функционира.
Изглеждаше това по следния начин:
![KeyDB като [потенциална] замяна за Redis.](/wp-content/uploads/2020/02/c0f55ca1d9f28f8c305bb74cdc77a84a.jpeg)
От страна на New Relic беше категорично идентифициран проблемът:
![KeyDB като [потенциална] замяна за Redis.](/wp-content/uploads/2020/02/ce72e290f84560d143f2d6c128358477.jpeg)
А ето статистиката за операцията get в Redis:
![KeyDB като [потенциална] замяна за Redis.](/wp-content/uploads/2020/02/31d98a6bb2985cfbe391976e24b8a8a6.jpeg)
След като проблемът беше съобщен в детайли на разработчиците, се установи, че „в момента не може да се реши проблемът“. Така започнаха търсенията на решение от страна на експлоатацията, а отговорът стана вече споменатият KeyDB.
Но преди да започнем с прегледа му, е важно да се спомене, че в проекта се използва standalone Redis, тъй като кластерното решение на базата на Sentinel значително отстъпва по забавяне (latency). Едно от очевидните решения беше създаването на няколко реплики на кеша: и нека приложението да се движи навсякъде с балансиране! Въпреки това, след консултации с разработчиците, бяхме принудени да отхвърлим тази опция поради активния и сложен механизъм за инвалидация на кеша в приложението. Същият проблем важеше и за шардироването на кеша.
Бърз преглед на KeyDB
В търсене на възможно решение на проблема открихме . Това е fork на Redis, разработен и разпространяван под отворена лицензия BSD. Проектът е сравнително млад: съществува от началото на 2019 година. Историята му е такава, че авторите също веднъж се сблъскаха с ограниченията на Redis… и решиха да направят свой fork. Освен това той не само че реши известните проблеми, но и получи допълнителни възможности, които са достъпни само в enterprise версията на Redis.
За тези, които искат да се запознаят по-подробно с KeyDB, има добра , която представя СУБД и кратки benchmark’и, сравняващи я със своя „родител“ — Redis.
Първо, привляка ни в KeyDB потенциалното решение на нашите проблеми, а също така ни заинтересуваха и някои допълнителни функции. Използването на KeyDB обещаваше следните предимства:
- постигане на пълна многонишкова работа;
- пълна и абсолютна съвместимост с Redis (за нас това беше особено важно, тъй като не беше възможно да правим каквито и да било доработки от страна на приложението), което също обещаваше безпроблемна миграция;
- вграден механизъм за резервно копие в S3 хранилище;
- опростена активна репликация;
- опростена кластеризация и шардинг без Sentinel и друг софтуер за поддръжка.
Над 3000 звезди и множество контрибутори в GitHub също изглеждаха обнадеждаващо. Приложението се развива активно и се поддържа, което е видно от комитите, общуването в issues, както и от затворените (приети) PR. Отговорите от основния поддръжник по всички фронтове винаги са доброжелателни и бързи. В общи линии, аргументите бяха достатъчни.
Миграция и резултати
Дори и да сметнем, че проектът за миграция беше вид авантюра (поради новизната на KeyDB), нямаше какво да губим. В крайна сметка, връщането на промените е достатъчно бързо и лесно — за щастие, цялата инфраструктура е изградена в Kubernetes, а вградените механизми перфектно решават подобни задачи.
Общо взето, подготвихме Helm шаблони, преместихме приложението в тестова среда на новата БД и пуснахме всичко, предавайки на QA отдела на клиента.
Започна тестването, което продължи около седмица и на детайлите, в които не се задълбочавахме. Знаем само, че клиентът провери стандартните функции на работа с Redis чрез PHP драйвера , както и проведе QA тестване на потребителския интерфейс. След това получихме зелена светлина: не бяха открити никакви странични ефекти при използването на новия софтуер. Тоест от гледна точка на приложението всичко остана неизменено..
Струва си да се отбележи, че и в конфигурацията не направихме нищо ново: буквално — просто заменихме използвания образ. Същото важи и за мониторинга и експортирането на метрики в Prometheus: перфектно работи с KeyDB и без каквито и да било доработки. По този начин, можем спокойно да кажем, че и от гледна точка на експлоатацията, това беше просто идеално преместване.
Благодарение на всичко това, след преминаването на приложението към нова СУБД, можете да не променяте нищо, а като "стабилизационна мярка" — да го оставите в този вид да работи в продукция за известно време. Въпреки това, ако искате да видите увеличаване на производителността (или въобще някакви промени), не трябва да забравяте, че по подразбиране параметърът KeyDB, отговарящ за многопоточността (server-threads), е равен на единица, тоест СУБД работи точно така, както Redis.
След преминаването, тестването и известно време работа на новото приложение (с KeyDB) решихме да повторим натоварващото тестване с същите параметри, които бяха използвани за Redis. Какви бяха резултатите?...
По графика на потреблението на CPU веднага стана очевидно отстраняването на проблемите с "потолка" в едно ядро: процесът започна да използва наличните ресурси:
![KeyDB като [потенциална] замяна за Redis.](/wp-content/uploads/2020/02/8a3a168507ef75a8e1cdf69e1d30d996.jpeg)
А по-късно се опитах доста силно да "измъчвам" приложението и видях потребление до три ядра...
Според показанията на New Relic, уеб приложението в цялост, имайки същото натоварване, започна да се държи значително по-адекватно. Някаква деградация на производителността все пак се наблюдаваше, обаче, сравнявайки с аналогичния график по-горе, можете сами да оцените съществен напредък:
![KeyDB като [потенциална] замяна за Redis.](/wp-content/uploads/2020/02/f46bf41bd6b8d190f5117d049ed2dce5.jpeg)
Показателят за забавяне на новата база данни (KeyDB) също се влоши, но оставаше в допустимите стойности:
![KeyDB като [потенциална] замяна за Redis.](/wp-content/uploads/2020/02/b9e0a3103a51707628a9f500dfdd53ad.jpeg)
По следния график е добре видно, че количеството заявки към самата KeyDB е подобно:
![KeyDB като [потенциална] замяна за Redis.](/wp-content/uploads/2020/02/0a067239194adb39eb3c3738fa73860e.jpeg)
Подводяки извод от тези синтетични тестове, можем да кажем, че както Redis, така и KeyDB показват значителна деградация на производителността в latency (40 ms+) при значителен ръст на количеството паралелни връзки (1000+). В нашия случай уеб приложението успяваше да „понижава” latency на Redis дори при по-ниско количество връзки (400+), макар че за KeyDB такова натоварване оставаше приемливо.
Изводи
В този пример прекрасно се вижда силата на Open Source общността по отношение на развитието на проекти, в които тя е заинтересована. В интернет срещнах страхотно изказване, чийто общ смисъл е следният: „Някоя голяма компания създава интересен продукт, прави част от функционалността му отворена, но най-важната част оставя платена. Общността се възползва-възползва, а след това някой просто ще вдигне ръка и ще направи fork, реализирайки именно тези платени функции и ги отваряйки за всички“. Ето KeyDB — точно такъв случай.
Говорейки за самата миграция, която премина учудващо лесно, не получихме толкова значителен ръст в производителността, какъвто може да се очаква, гледайки графиките на авторите на KeyDB… Въпреки това, това е само нашият частен случай, в който може да има много отклонения, свързващи се и с пресловутата архитектура на приложението (например, огромно количество команди get в Redis вместо по-продуктивния вариант на агрегираните заявки mget…). Независимо от това, положителни резултати успяхме да постигнем, а заедно с тях — много полезни функции, които още само ще внедряваме в близко бъдеще.
Като цяло, KeyDB изглежда обещаващо: с натрупването на практически опит при работа с тази СУБД (което все още предстои!) и развитието на самия проект, ще разгледаме възможността за нейното приложение и в други ситуации.
Но не бива да разглеждате тази статия като ръководство (и особено — призив) за всеобхватно отклонение от Redis в полза на KeyDB. Въпреки нашия позитивен опит, очевидно е, че това не е сребърна пушка. Случаят беше доста специфичен: конкретно за решаване на моментен проблем в ситуация, когато трябваше да направим това бързо и с минимални разходи, такова решение се оправда. Ще бъде ли KeyDB полезен във вашия случай? Най-малкото, вече знаете, че такава потенциална възможност съществува.
P.S.
Прочетете също в нашия блог:
- «»;
- «»;
- «»;
- «».
Източник: habr.com
