Относно преминаването от Redis към Redis-cluster

Относно преминаването от Redis към Redis-cluster

Стигайки до продукт, който се разработва повече от десетилетие, изобщо не е изненадващо да открием остарели технологии в него. Но какво ще стане, ако след шест месеца трябва да поддържате натоварването 10 пъти по-високо, а цената на падането ще се увеличи стотици пъти? В този случай имате нужда от готин Highload Engineer. Но поради липсата на камериерка, те ми повериха решаването на проблема. В първата част на статията ще ви разкажа как преминахме от Redis към Redis-cluster, а във втората част ще дам съвети как да започнете да използвате клъстера и на какво да обърнете внимание, когато го използвате.

Технологичен избор

Толкова ли е лошо? отделен Redis (самостоятелен redis) в конфигурация от 1 главен и N подчинени? Защо го наричам остаряла технология?

Не, Redis не е толкова лош... Има обаче някои недостатъци, които не могат да бъдат пренебрегнати.

  • Първо, Redis не поддържа механизми за възстановяване след авария след главен отказ. За да решим този проблем, използвахме конфигурация с автоматично прехвърляне на VIP към нов главен, смяна на ролята на един от подчинените и превключване на останалите. Този механизъм работеше, но не можеше да се нарече надеждно решение. Първо, възникнаха фалшиви аларми и второ, беше за еднократна употреба и след операцията бяха необходими ръчни действия за зареждане на пружината.

  • Второ, наличието само на един мастер доведе до проблема с шардинга. Трябваше да създадем няколко независими клъстера „1 master и N slaves“, след което ръчно да разпределим базите данни между тези машини и да се надяваме, че утре една от базите данни няма да набъбне толкова много, че да се наложи да бъде преместена в отделна инстанция.

Какви са опциите?

  • Най-скъпото и богато решение е Redis-Enterprise. Това е решение в кутия с пълна техническа поддръжка. Въпреки факта, че изглежда идеално от техническа гледна точка, не ни подхождаше по идеологически причини.
  • Redis-клъстер. Извън кутията има поддръжка за главен отказ и шардинг. Интерфейсът почти не се различава от обикновената версия. Изглежда обещаващо, ще говорим за клопките по-късно.
  • Tarantool, Memcache, Aerospike и др. Всички тези инструменти правят почти едно и също нещо. Но всеки има своите недостатъци. Решихме да не слагаме всички яйца в една кошница. Използваме Memcache и Tarantool за други задачи и, гледайки напред, ще кажа, че в нашата практика имаше повече проблеми с тях.

Специфика на използване

Нека да разгледаме какви проблеми сме решавали в миналото с Redis и каква функционалност сме използвали:

  • Кеширане преди заявки към отдалечени услуги като 2GIS | Голанг

    GET SET MGET MSET "SELECT DB"

  • Кеш преди MYSQL | PHP

    GET SET MGET MSET SCAN "KEY BY PATTERN" "SELECT DB"

  • Основното хранилище за услугата за работа със сесии и координати на водача | Голанг

    GET SET MGET MSET "SELECT DB" "ADD GEO KEY" "GET GEO KEY" SCAN

Както можете да видите, няма висша математика. Тогава каква е трудността? Нека разгледаме всеки метод поотделно.

метод
описание
Характеристики на Redis-cluster
Решение

ПРИГОТВИ СЕ
Ключ за писане/четене

MGET MSET
Запис/четене на множество ключове
Ключовете ще бъдат на различни възли. Готовите библиотеки могат да изпълняват много операции само в рамките на един възел
Заменете MGET с конвейер от N GET операции

ИЗБЕРЕТЕ DB
Изберете основата, с която ще работим
Не поддържа множество бази данни
Поставете всичко в една база данни. Добавете префикси към ключовете

SCAN
Преминете през всички ключове в базата данни
Тъй като имаме една база данни, преминаването през всички ключове в клъстера е твърде скъпо
Поддържайте инвариант в рамките на един ключ и направете HSCAN на този ключ. Или откажете напълно

GEO
Операции с геоключ
Geokey не е сегментиран

КЛЮЧ ПО ШАРКА
Търсене на ключ по образец
Тъй като имаме една база данни, ще търсим във всички ключове в клъстера. Много скъпо
Откажете или поддържайте инварианта, както в случая със SCAN

Redis срещу Redis-клъстер

Какво губим и какво печелим при преминаване към клъстер?

  • Недостатъци: губим функционалността на няколко бази данни.
    • Ако искаме да съхраняваме логически несвързани данни в един клъстер, ще трябва да направим патерици под формата на префикси.
    • Губим всички „базови“ операции, като SCAN, DBSIZE, CLEAR DB и т.н.
    • Мултиоперациите станаха много по-трудни за изпълнение, тъй като може да изискват достъп до няколко възела.
  • Предимства:
    • Толерантност към грешки под формата на master failover.
    • Шардинг от страна на Redis.
    • Прехвърляйте данни между възлите атомарно и без престой.
    • Добавете и преразпределете капацитет и товари без престой.

Бих заключил, че ако не е необходимо да осигурите високо ниво на устойчивост на грешки, тогава преминаването към клъстер не си струва, защото това може да бъде нетривиална задача. Но ако първоначално избирате между отделна версия и версия на клъстер, тогава трябва да изберете клъстер, тъй като не е по-лош и освен това ще ви освободи от част от главоболията

Подготовка за преместване

Да започнем с изискванията за преместване:

  • Трябва да е безпроблемно. Пълното спиране на услугата за 5 минути не ни устройва.
  • Трябва да бъде възможно най-безопасно и постепенно. Искам малко да контролирам ситуацията. Не искаме да изхвърлим всичко наведнъж и да се молим за бутона за връщане назад.
  • Минимална загуба на данни при преместване. Разбираме, че ще бъде много трудно да се движим атомарно, така че позволяваме известна десинхронизация между данните в обикновения и клъстерирания Redis.

Поддръжка на клъстер

Точно преди преместването трябва да помислим дали можем да поддържаме клъстера:

  • Графики. Ние използваме Prometheus и Grafana за графично натоварване на процесора, използване на паметта, брой клиенти, брой операции GET, SET, AUTH и т.н.
  • Експертиза. Представете си, че утре ще имате огромен клъстер под ваша отговорност. Ако се счупи, никой освен вас не може да го поправи. Ако той започне да забавя, всички ще хукнат към вас. Ако трябва да добавите ресурси или да преразпределите товара, върнете се при вас. За да не станете сиви на 25, препоръчително е да предвидите тези случаи и да проверите предварително как ще се държи технологията при определени действия. Нека поговорим за това по-подробно в раздела „Експертиза“.
  • Мониторинг и сигнали. Когато един клъстер се разпадне, вие искате да сте първият, който ще научи за това. Тук се ограничихме до известие, че всички възли връщат една и съща информация за състоянието на клъстера (да, случва се различно). И други проблеми могат да бъдат забелязани по-бързо чрез предупреждения от клиентските услуги на Redis.

прелез

Как ще се движим:

  • На първо място, трябва да подготвите библиотека за работа с клъстера. Взехме go-redis като основа за версията Go и я променихме малко, за да ни подхожда. Ние внедрихме Multi-methods чрез тръбопроводи и също така леко коригирахме правилата за повтарящи се заявки. PHP версията имаше повече проблеми, но в крайна сметка се спряхме на php-redis. Те наскоро въведоха поддръжка на клъстери и изглежда добре според нас.
  • След това трябва да разположите самия клъстер. Това се прави буквално с две команди, базирани на конфигурационния файл. Ще обсъдим настройката по-подробно по-долу.
  • За постепенно преместване използваме сух режим. Тъй като имаме две версии на библиотеката с един и същ интерфейс (едната за обикновената версия, другата за клъстера), не струва нищо да създадем обвивка, която ще работи с отделна версия и паралелно ще дублира всички заявки към клъстера, сравнете отговорите и запишете несъответствията в регистрационните файлове (в нашия случай в NewRelic). По този начин, дори ако версията на клъстера се повреди по време на внедряването, нашата продукция няма да бъде засегната.
  • След като пуснахме клъстера в сух режим, можем спокойно да разгледаме графиката на несъответствията в отговорите. Ако процентът на грешки бавно, но сигурно се движи към някаква малка константа, тогава всичко е наред. Защо все още има несъответствия? Тъй като записът в отделна версия се извършва малко по-рано, отколкото в клъстера, и поради microlag данните могат да се различават. Всичко, което остава, е да разгледаме регистрационните файлове на несъответствията и ако всички те се обясняват с неатомичността на записа, тогава можем да продължим.
  • Сега можете да превключите сухия режим в обратната посока. Ще пишем и четем от клъстера и ще го дублираме в отделна версия. За какво? През следващата седмица бих искал да наблюдавам работата на клъстера. Ако внезапно се окаже, че има проблеми при пиково натоварване или не сме взели нещо предвид, винаги имаме аварийно връщане към стария код и текущите данни благодарение на сухия режим.
  • Остава само да деактивирате сухия режим и да демонтирате отделната версия.

изпит

Първо, накратко за дизайна на клъстера.

На първо място, Redis е магазин за ключ-стойност. Като ключове се използват произволни низове. Като стойности могат да се използват числа, низове и цели структури. Има много от последните, но за разбирането на общата структура това не е важно за нас.
Следващото ниво на абстракция след ключовете са слотовете (SLOTS). Всеки ключ принадлежи към един от 16 383 слота. Във всеки слот може да има произволен брой ключове. Така всички ключове са разделени на 16 383 несвързани комплекта.
Относно преминаването от Redis към Redis-cluster

След това трябва да има N главни възли в клъстера. Всеки възел може да се разглежда като отделен екземпляр на Redis, който знае всичко за другите възли в клъстера. Всеки главен възел съдържа определен брой слотове. Всеки слот принадлежи само на един главен възел. Всички слотове трябва да бъдат разпределени между възлите. Ако някои слотове не са разпределени, ключовете, съхранени в тях, ще бъдат недостъпни. Има смисъл да стартирате всеки главен възел на отделна логическа или физическа машина. Също така си струва да запомните, че всеки възел работи само на едно ядро ​​и ако искате да стартирате множество екземпляри на Redis на една и съща логическа машина, уверете се, че те работят на различни ядра (не сме опитвали това, но на теория трябва да работи) . По същество главните възли осигуряват редовно шардинг, а повече главни възли позволяват мащабиране на заявки за запис и четене.

След като всички ключове са разпределени между слотовете и слотовете са разпръснати между главните възли, произволен брой подчинени възли могат да бъдат добавени към всеки главен възел. В рамките на всяка такава връзка главен-подчинен нормалната репликация ще работи. Необходими са подчинени устройства за мащабиране на заявките за четене и за преход при отказ в случай на повреда на главния.
Относно преминаването от Redis към Redis-cluster

Сега нека поговорим за операциите, които би било по-добре да можете да правите.

Ще имаме достъп до системата чрез Redis-CLI. Тъй като Redis няма нито една входна точка, можете да извършвате следните операции на всеки от възлите. Във всяка точка отделно обръщам внимание на възможността за извършване на операцията под товар.

  • Първото и най-важно нещо, от което се нуждаем, е работата на клъстерните възли. Той връща състоянието на клъстера, показва списък с възли, техните роли, разпределение на слотовете и т.н. Повече информация може да бъде получена чрез информация за клъстери и слотове за клъстери.
  • Би било хубаво да можете да добавяте и премахвате възли. За тази цел има операции за среща на клъстер и забравяне на клъстер. Моля, обърнете внимание, че забравянето на клъстера трябва да се приложи към ВСЕКИ възел, както главните, така и репликите. И срещата на клъстера трябва да бъде извикана само на един възел. Тази разлика може да бъде смущаваща, така че е най-добре да научите за нея, преди да започнете да работите с вашия клъстер. Добавянето на възел се извършва безопасно в битка и не влияе по никакъв начин на работата на клъстера (което е логично). Ако възнамерявате да премахнете възел от клъстера, трябва да се уверите, че в него няма останали слотове (в противен случай рискувате да загубите достъп до всички ключове на този възел). Също така, не изтривайте главен, който има подчинени устройства, в противен случай ще се извърши ненужно гласуване за нов главен. Ако възлите вече нямат слотове, тогава това е малък проблем, но защо се нуждаем от допълнителни възможности за избор, ако можем първо да изтрием подчинените.
  • Ако трябва принудително да размените главните и подчинените позиции, тогава командата за преодоляване на клъстера ще свърши работа. Когато го извиквате в битка, трябва да разберете, че господарят няма да бъде наличен по време на операцията. Обикновено превключването става за по-малко от секунда, но не е атомарно. Можете да очаквате, че някои заявки към главния ще се провалят през това време.
  • Преди да премахнете възел от клъстера, в него не трябва да има останали слотове. По-добре е да ги преразпределите с помощта на командата reshard на клъстера. Слотовете ще се прехвърлят от един мастер на друг. Цялата операция може да отнеме няколко минути, зависи от обема на прехвърляните данни, но процесът на прехвърляне е безопасен и не засяга работата на клъстера по никакъв начин. Така всички данни могат да се прехвърлят от един възел към друг директно при натоварване и без да се притеснявате за тяхната наличност. Има обаче и тънкости. Първо, прехвърлянето на данни е свързано с определено натоварване на възлите на получателя и изпращача. Ако възелът получател вече е силно натоварен на процесора, тогава не трябва да го зареждате с получаване на нови данни. Второ, щом не остане нито един слот на изпращащия главен, всички негови подчинени незабавно ще отидат при главния, към който са прехвърлени тези слотове. И проблемът е, че всички тези роби ще искат да синхронизират данните наведнъж. И ще имате късмет, ако е частична, а не пълна синхронизация. Вземете това предвид и комбинирайте операциите по прехвърляне на слотове и деактивиране/прехвърляне на подчинени устройства. Или се надявайте, че имате достатъчна граница на безопасност.
  • Какво трябва да направите, ако по време на прехвърлянето установите, че сте загубили слотовете си някъде? Надявам се, че този проблем не ви засяга, но ако се случи, има операция за коригиране на клъстера. Най-малкото тя ще разпръсне слотовете по възлите в произволен ред. Препоръчвам да проверите работата му, като първо премахнете възела с разпределени слотове от клъстера. Тъй като данните в неразпределените слотове вече са недостъпни, твърде късно е да се притеснявате за проблеми с наличността на тези слотове. От своя страна операцията няма да засегне разпределените слотове.
  • Друга полезна операция е мониторът. Тя ви позволява да видите в реално време целия списък от заявки, отиващи към възела. Освен това можете да го grep и да разберете дали има необходимия трафик.

Струва си да се спомене и главната процедура за преход при срив. Накратко, съществува и според мен работи чудесно. Не си мислете обаче, че ако изключите захранващия кабел на машина с главен възел, Redis веднага ще превключи и клиентите няма да забележат загубата. В моята практика превключването става за няколко секунди. През това време някои от данните ще бъдат недостъпни: открива се недостъпност на главния, възлите гласуват за нов, подчинените се превключват, данните се синхронизират. Най-добрият начин да се уверите сами, че схемата работи, е да провеждате локални упражнения. Повдигнете клъстера на вашия лаптоп, дайте му минимално натоварване, симулирайте срив (например чрез блокиране на портовете) и оценете скоростта на превключване. Според мен само след като играете по този начин ден-два можете да сте уверени в работата на технологията. Е, или се надявам, че софтуерът, който използва половината интернет, вероятно работи.

Конфигурация

Често конфигурацията е първото нещо, от което се нуждаете, за да започнете да работите с инструмента. И когато всичко работи, вие дори не искате да докосвате конфигурацията. Отнема известно усилие, за да се принудите да се върнете към настройките и да ги прегледате внимателно. По мои спомени имахме поне два сериозни повреди поради невнимание към конфигурацията. Обърнете специално внимание на следните точки:

  • timeout 0
    Време, след което неактивните връзки се затварят (в секунди). 0 - не затваряйте
    Не всяка наша библиотека успя да затвори правилно връзките. Като деактивираме тази настройка, рискуваме да достигнем ограничението за броя клиенти. От друга страна, ако има такъв проблем, автоматичното прекъсване на загубени връзки ще го маскира и ние може да не забележим. Освен това не трябва да активирате тази настройка, когато използвате постоянни връзки.
  • Запазване на xy & appendonly да
    Запазване на RDB снимка.
    По-долу ще обсъдим подробно проблемите с RDB/AOF.
  • stop-writes-on-bgsave-error no & slave-serve-stale-data да
    Ако е разрешено, ако моментната снимка на RDB се повреди, главният ще спре да приема заявки за промяна. Ако връзката с главния се загуби, подчиненият може да продължи да отговаря на заявки (да). Или ще спре да отговаря (не)
    Не сме доволни от ситуацията, в която Redis се превръща в тиква.
  • repl-ping-slave-period 5
    След този период от време ще започнем да се тревожим, че главната система се е повредила и е време да извършим процедурата за преместване при срив.
    Ще трябва ръчно да намерите баланс между фалшиви положителни резултати и задействане на отказ. В нашата практика това са 5 секунди.
  • repl-backlog-size 1024mb & epl-backlog-ttl 0
    Можем да съхраняваме точно толкова данни в буфер за неуспешна реплика. Ако буферът свърши, ще трябва да синхронизирате напълно.
    Практиката показва, че е по-добре да зададете по-висока стойност. Има много причини, поради които една реплика може да започне да изостава. Ако изостава, тогава най-вероятно вашият господар вече се бори да се справи и пълната синхронизация ще бъде последната капка.
  • максимум клиенти 10000 XNUMX
    Максимален брой еднократни клиенти.
    Според нашия опит е по-добре да зададете по-висока стойност. Redis се справя отлично с 10k връзки. Просто се уверете, че има достатъчно гнезда в системата.
  • maxmemory-policy volatile-ttl
    Правилото, по което ключовете се изтриват при достигане на ограничението на наличната памет.
    Тук е важно не самото правило, а разбирането как ще се случи това. Redis може да бъде похвален за способността му да работи нормално, когато лимитът на паметта е достигнат.

Проблеми с RDB и AOF

Въпреки че самият Redis съхранява цялата информация в RAM, има и механизъм за запис на данни на диск. По-точно три механизма:

  • RDB-моментна снимка - пълна моментна снимка на всички данни. Задайте с помощта на конфигурацията SAVE XY и гласи „Запазване на пълна моментна снимка на всички данни на всеки X секунди, ако поне Y ключове са променени.“
  • Файл само за добавяне - списък с операции в реда, в който се изпълняват. Добавя нови входящи операции към файла на всеки X секунди или на всеки Y операции.
  • RDB и AOF са комбинация от предишните две.

Всички методи имат своите предимства и недостатъци, няма да ги изброявам всички, просто ще обърна внимание на моменти, които според мен не са очевидни.

Първо, запазването на моментна снимка на RDB изисква извикване на FORK. Ако има много данни, това може да блокира целия Redis за период от няколко милисекунди до секунда. Освен това системата трябва да разпредели памет за такава моментна снимка, което води до необходимостта да се поддържа двойно количество RAM на логическата машина: ако 8 GB са разпределени за Redis, тогава 16 GB трябва да са налични на виртуалната машина с то.

Второ, има проблеми с частичната синхронизация. В режим AOF, когато подчиненото устройство е свързано отново, вместо частична синхронизация може да се извърши пълна синхронизация. Защо се случва това, не можах да разбера. Но си струва да запомните това.

Тези две точки вече ни карат да се замислим дали наистина се нуждаем от тези данни на диска, ако всичко вече е дублирано от роби. Данните могат да бъдат загубени само ако всички подчинени устройства се повредят и това е проблем на ниво „пожар в DC“. Като компромис можете да предложите да запазвате данни само на подчинени устройства, но в този случай трябва да сте сигурни, че тези подчинени устройства никога няма да станат главни по време на възстановяване след авария (за това има настройка за приоритет на подчинени устройства в тяхната конфигурация). За себе си във всеки конкретен случай се замисляме дали е необходимо да записваме данни на диск и най-често отговорът е „не“.

Заключение

В заключение, надявам се, че успях да дам обща представа за това как работи redis-cluster за тези, които изобщо не са чували за него, и също така обърнах внимание на някои неочевидни точки за тези, които го използват за дълго време.
Благодаря за отделеното време и, както винаги, коментарите по темата са добре дошли.

Източник: www.habr.com

Добавяне на нов коментар