Аб пераездзе з Redis на Redis-cluster

Аб пераездзе з Redis на Redis-cluster

Прыходзячы ў прадукт, які развіваецца больш за дзесятак гадоў, зусім не дзіўна сустрэць у ім састарэлыя тэхналогіі. Але што калі праз паўгода вы павінны трымаць нагрузку ў 10 разоў вышэй, а кошт падзенняў павялічыцца ў сотні разоў? У гэтым выпадку вам неабходны круты Highload Engineer. Але з-за адсутнасці пакаёўкі такога, вырашаць праблему даверылі мне. У першай частцы артыкула я раскажу, як мы пераязджалі з Redis на Redis-cluster, а ў другой частцы дам парады, як пачаць карыстацца кластарам і на што звярнуць увагу пры эксплуатацыі.

Выбар тэхналогіі

Ці так дрэнны асобны Redis (standalone redis) у канфігурацыі 1 майстар і N слейваў? Чаму я называю яго састарэлай тэхналогіяй?

Не, Redis не такі дрэнны… Аднак, ёсць некаторыя недахопы якія нельга ігнараваць.

  • Па-першае, Redis не падтрымлівае механізмы аварыйнага аднаўлення пасля падзення майстра. Для вырашэння гэтай праблемы мы выкарыстоўвалі канфігурацыю з аўтаматычным перакіданнем VIP-ов на новы майстар, зменай ролі аднаго са слейваў і пераключэннем астатніх. Гэты механізм працаваў, але назваць яго надзейным рашэннем было нельга. У першых, здараліся ілжывыя спрацоўванні, а ў другіх, ён быў аднаразовым, і пасля спрацоўвання патрабаваліся ручныя дзеянні па ўзводзе спружыны.

  • Па-другое, наяўнасць толькі аднаго майстра прыводзіла да праблемы шардзіравання. Даводзілася ствараць некалькі незалежных кластараў «1 майстар і N слейваў», затым уручную разносіць базы па гэтых машынах і спадзявацца, што заўтра адна з баз не распухне настолькі, што яе давядзецца выносіць на асобны інстанс.

Якія ёсць варыянты?

  • Самае дарагое і багатае рашэнне – Redis-Enterprise. Гэтае скрыначнае рашэнне з поўнай тэхнічнай падтрымкай. Нягледзячы на ​​тое, што яно выглядае ідэальным з тэхнічнага пункту гледжання, нам не падышло з ідэалагічных меркаванняў.
  • Redis-cluster. Са скрынкі ёсць падтрымка аварыйнага пераключэння майстра і шаліравання. Інтэрфейс амаль не адрозніваецца ад звычайнай версіі. Выглядае шматабяцальна, пра падводныя камяні пагаворым далей.
  • Tarantool, Memcache, Aerospike і іншыя. Усе гэтыя прылады робяць прыкладна тое ж самае. Але ў кожнага ёсць свае недахопы. Мы вырашылі не класці ўсе яйкі ў адзін кошык. Memcache і Tarantool мы выкарыстоўваем для іншых задач, і, забягаючы наперад, скажу, што на нашай практыцы праблем з імі было больш.

Спецыфіка выкарыстання

Давайце зірнем, якія задачы мы гістарычна вырашалі Redis'ам і якую функцыянальнасць выкарыстоўвалі:

  • Кеш перад запытамі да выдаленых сэрвісаў накшталт 2GIS Golang

    GET SET MGET MSET "SELECT DB"

  • Кэш перад MYSQL | PHP

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

  • Асноўнае сховішча для сэрвісу працы з сесіямі і каардынатамі вадзіцеляў Golang

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

Як бачыце, ніякай вышэйшай матэматыкі. У чым тады складанасць? Давайце разбяром асобна па кожным метадзе.

метад
Апісанне
Асаблівасці Redis-cluster
рашэнне

АТРЫМАЙЦЕСЯ
Запісаць/прачытаць ключ

MGET MSET
Запісаць/прачытаць некалькі ключоў
Ключы будуць ляжаць на розных нодах. Гатовыя бібліятэкі ўмеюць рабіць Multi-аперацыі толькі ў рамках адной ноды
Замяніць MGET на pipeline з N GET аперацый

SELECT DB
Выбраць базу, з якой будзем працаваць
Не падтрымлівае некалькі баз дадзеных
Складаць усё ў адну базу. Дадаць да ключоў прэфіксы

SCAN
Прайсці па ўсіх ключах у базе
Паколькі ў нас адна база, праходзіць па ўсіх ключах у кластары занадта затратна
Падтрымліваць інварыянт ўнутры аднаго ключа і рабіць HSCAN па гэтым ключы. Або адмовіцца зусім

GEO
Аперацыі працы з геаключом
Геаключ не шаруецца

KEY BY PATTERN
Пошук ключа па патэрну
Паколькі ў нас адна база, будзем шукаць па ўсіх ключах у кластары. Занадта затратна
Адмовіцца ці падтрымліваць інварыянт, як і ў выпадку са SCAN-ам

Redis vs Redis-cluster

Што мы губляем і што атрымліваем пры пераходзе на кластар?

  • Недахопы: страчваем функцыянальнасць некалькіх баз.
    • Калі мы хочам захоўваць у адным кластары лагічна не звязаныя дадзеныя, давядзецца рабіць мыліцы ў выглядзе прэфіксаў.
    • Страчваем усе аперацыі "па базе", такія як SCAN, DBSIZE, CLEAR DB і да т.п.
    • Multi-аперацыі сталі значна складаней у рэалізацыі, таму што можа патрабавацца зварот да некалькіх нодаў.
  • добрыя якасці:
    • Адмаўстойлівасць у выглядзе аварыйнага пераключэння майстра.
    • Шардзіравання на баку Redis.
    • Перанос даных паміж нодамі атамарна і без прастояў.
    • Даданне і пераразмеркаванне магутнасцей і нагрузак без прастояў.

Я б зрабіў выснову, што калі вам не трэба забяспечваць высокі ўзровень адмоваўстойлівасці, то пераезд на кластар таго не варта, бо гэта можа быць нетрывіяльнай задачай. Але калі першапачаткова выбіраць паміж асобнай версіяй і кластарнай, то варта выбіраць кластар, бо ён нічым не горшы і ў дадатак здыме з вас частку галаўнога болю.

Падрыхтоўка да пераезду

Пачнём з патрабаванняў да пераезду:

  • Ён павінен быць бясшвоўным. Поўны прыпынак сэрвісу на 5 хвілін нас не задавальняе.
  • Ён павінен быць максімальна бяспечным і паступовым. Жадаецца мець нейкі кантроль над сітуацыяй. Бухнуць адразу ўсё і маліцца над кнопкай адкату мы не жадаем.
  • Мінімальныя страты даных пры пераездзе. Мы разумеем, што пераехаць атамарна будзе вельмі складана, таму дапушчаем некаторую рассінхранізацыю паміж дадзенымі ў звычайным і кластарным Redis.

Абслугоўванне кластара

Перад самым пераездам варта задумацца аб тым, а ці можам мы падтрымліваць кластар:

  • Графікі. Мы выкарыстоўваем Prometheus і Grafana для графікаў загрузкі працэсараў, занятай памяці, колькасці кліентаў, колькасці аперацый GET, SET, AUTH і да т.п.
  • Экспертыза. Уявіце, што заўтра пад вашай адказнасцю будзе вялізны кластар. Калі ён зламаецца, ніхто, акрамя вас, паправіць яго не зможа. Калі ён пачне тармазіць - усё пабягуць да вас. Калі трэба дадаць рэсурсы або пераразмеркаваць нагрузку - зноў да вас. Каб не пасівець у 25, пажадана прадугледзець гэтыя выпадкі і праверыць загадзя, як тэхналогія павядзе сябе пры тых ці іншых дзеяннях. Пагаворым пра гэта падрабязней у раздзеле "Экспертыза".
  • Маніторынгі і абвесткі. Калі кластар ламаецца, пра гэта хочацца даведацца першым. Тут мы абмежаваліся апавяшчэннем аб тым, што ўсе ноды вяртаюць аднолькавую інфармацыю аб стане кластара (так, бывае і па-іншаму). А астатнія праблемы хутчэй заўважыць па абвестках сэрвісаў-кліентаў Redis.

Пераезд

Як будзем пераязджаць:

  • У першую чаргу трэба падрыхтаваць бібліятэку для работы з кластарам. У якасці асновы для версіі на Gо мы ўзялі go-redis і крыху змянілі пад сябе. Рэалізавалі Multi-метады праз pipeline-ы, а таксама крыху паправілі правілы паўтарэння запытаў. З версіяй для PHP узнікла больш праблем, але ў канчатковым рахунку мы спыніліся на php-redis. Нядаўна яны ўкаранілі падтрымку кластара, і на наш погляд яна выглядае добра.
  • Далей трэба разгарнуць сам кластар. Робіцца гэта літаральна ў дзве каманды на аснове канфігурацыйнага файла. Больш падрабязна настройку абмяркуем ніжэй.
  • Для паступовага пераезду мы выкарыстоўваем dry-mode. Так як у нас ёсць дзве версіі бібліятэкі з аднолькавым інтэрфейсам (адна для звычайнай версіі, іншая для кластара), нічога не варта зрабіць абгортку, якая будзе працаваць з асобнай версіяй і паралельна дубліраваць усе запыты ў кластар, параўноўваць адказы і пісаць разыходжанні ў логі ( у нашым выпадку ў NewRelic). Такім чынам, нават калі пры выкатцы кластарная версія зламаецца, наш production гэта не закране.
  • Выкаціўшы кластар у dry-рэжыме, мы можам спакойна глядзець на графік разыходжанняў адказаў. Калі доля памылак павольна, але дакладна рухаецца да некаторай невялікай канстанты, значыць, усё добра. Чаму разыходжанні ўсё роўна ёсць? Таму што запіс у асобнай версіі адбываецца некалькі раней, чым у кластары, і за кошт мікралага дадзеныя могуць разыходзіцца. Засталося толькі паглядзець на логі разыходжанняў, і калі ўсе яны вытлумачальныя неатамарнасцю запісу, то можна ісці далей.
  • Цяпер можна пераключыць dry-mode у адваротны бок. Пісаць і чытаць будзем з кластара, а дубліраваць у асобную версію. Навошта? На працягу наступнага тыдня хочацца паназіраць за працай кластара. Калі раптам высветліцца, што ў піку нагрузкі ёсць праблемы, ці мы нешта не ўлічылі, у нас заўсёды ёсць аварыйны адкат на стары код і актуальныя дадзеныя дзякуючы dry-mode.
  • Засталося адключыць dry-mode і дэмантаваць асобную версію.

Экспертыза

Спачатку коратка аб прыладзе кластара.

У першую чаргу, Redis – key-value сховішча. У якасці ключа выкарыстоўваюцца адвольныя радкі. У якасці значэнняў могуць выкарыстоўвацца лікі, радкі і цэлыя структуры. Апошніх вялікае мноства, але для разумення агульнай прылады нам гэта не важна.
Наступны пасля ключоў узровень абстракцыі - слоты (SLOTS). Кожны ключ належыць аднаму з 16 слотаў. Унутры кожнага слота можа быць колькі-заўгодна ключоў. Такім чынам, усе ключы распадаюцца на 383 неперасякальных мностваў.
Аб пераездзе з Redis на Redis-cluster

Далей, у кластары павінна быць N майстар-нод. Кожную ноду можна прадстаўляць як асобны інстанс Redis, які ведае ўсё пра іншыя ноды ўнутры кластара. Кожная майстар-нода змяшчае некаторую колькасць слотаў. Кожны слот належыць толькі адной майстар-нодзе. Усе слоты трэба размеркаваць паміж нодамі. Калі нейкія слоты не размеркаваны, то якія захоўваюцца ў іх ключы будуць недаступныя. Кожную майстар-ноду мае сэнс запускаць на асобнай лагічнай ці фізічнай машыне. Таксама варта памятаць, што кожная нода працуе толькі на адным ядры, і калі вы жадаеце запусціць на адной лагічнай машыне некалькі асобнікаў Redis, то пераканайцеся, што яны будуць працаваць на розных ядрах (мы не спрабавалі так рабіць, але ў тэорыі ўсё павінна працаваць). . Па сутнасці, майстар-ноды забяспечваюць звычайнае шардаванне, і большую колькасць майстар-нод дазваляе маштабаваць запыты на запіс і чытанне.

Пасля таго, як усе ключы размеркаваны па слотах, а слоты раскіданыя па майстар-нодах, да кожнай майстар-нодзе можна дадаць адвольную колькасць слейв-нод. Унутры кожнага такога звязка "майстар-слейв" будзе працаваць звычайная рэплікацыя. Cлейвы патрэбныя для маштабавання запытаў на чытанне і для аварыйнага пераключэння ў выпадку выхаду са строю майстра.
Аб пераездзе з Redis на Redis-cluster

Цяпер пагаворым аб аперацыях, якія лепш бы ўмець рабіць.

Звяртацца да сістэмы мы будзем праз Redis-CLI. Паколькі ў Redis няма адзінай кропкі ўваходу, выконваць наступныя аперацыі можна на любой з нод. У кожным пункце асобна зважаю на магчымасць выканання аперацыі пад нагрузкай.

  • Першае і самае галоўнае, што нам спатрэбіцца: аперацыя cluster nodes. Яна вяртае стан кластара, паказвае спіс нод, іх ролі, размеркаванне слотаў і да т.п. Дадатковыя звесткі можна атрымаць з дапамогай cluster info і cluster slots.
  • Добра было б умець дадаваць і выдаляць ноды. Для гэтага ёсць аперацыі cluster meet і cluster forget. Звярніце ўвагу, што cluster forget неабходна прымяніць да КОЖНАЙ ноды, як да майстроў, так і да рэплікаў. А cluster meet дастаткова выклікаць толькі на адной нодзе. Такое адрозненне можа бянтэжыць, так што лепш пазнаць пра яго да таго, як запусцілі кластар у эксплуатацыю. Даданне ноды бяспечна выконваецца ў баі і ніяк не закранае працу кластара (што лагічна). Калі ж вы збіраецеся выдаліць ноду з кластара, тое варта пераканацца, што на ёй не засталося слотаў (інакш вы рызыкуеце страціць доступ да ўсіх ключоў на гэтай нодзе). Таксама не выдаляйце майстар, у якога ёсць слейвы, інакш будзе выконвацца непатрэбнае галасаванне за новага майстра. Калі на нодах ужо няма слотаў, тое гэта невялікая праблема, але навошта нам лішнія выбары, калі можна спачатку выдаліць слейвы.
  • Калі трэба сілком памяняць месцамі майстар і слейв, то падыдзе каманда cluster failover. Выклікаючы яе ў баі, трэба разумець, што на працягу выканання аперацыі майстар будзе недаступны. Звычайна пераключэнне адбываецца менш, чым за секунду, але не атамарна. Можаце разлічваць, што частка запытаў да майстра тым часам завершыцца з памылкай.
  • Перад выдаленнем ноды з кластара на ёй не павінна заставацца слотаў. Пераразмяркоўваць іх лепш з дапамогай каманды cluster reshard. Слоты будуць перанесены з аднаго майстра, на іншы. Уся аперацыя можа займаць некалькі мінуць, гэта залежыць ад аб'ёму пераносных дадзеных, аднак працэс пераносу бяспечны і на працы кластара ніяк не адбіваецца. Такім чынам, усе дадзеныя можна перанесці з адной ноды на іншую прама пад нагрузкай, і не турбавацца аб іх даступнасці. Аднак ёсць і тонкасці. Па-першае, перанос дадзеных спалучаны з вызначанай нагрузкай на ноду атрымальніка і адпраўніка. Калі нода атрымальніка ўжо моцна загружана па працэсары, то не варта нагружаць яе яшчэ і прыёмам новых дадзеных. Па-другое, як толькі на майстру-адпраўніку не застанецца ніводнага слота, усе яго слейвы тут жа пяройдуць да майстра, на які гэтыя слоты былі перанесены. І праблема ў тым, што ўсе гэтыя слейвы зараз захочуць сінхранізаваць дадзеныя. І вам яшчэ пашанцуе, калі гэта будзе частковая, а не поўная сінхранізацыя. Улічвайце гэта, і спалучайце аперацыі пераносу слотаў і адключэнні/пераносу слейваў. Ці спадзявайцеся, што ў вас дастатковы запас трываласці.
  • Што рабіць, калі пры пераносе вы выявілі, што кудысьці страцілі слоты? Спадзяюся, гэтая праблема вас не закране, але калі што, есць аперацыя cluster fix. Яна худа-бедна раскідае слоты па нодах у выпадковым парадку. Рэкамендую праверыць яе працу, папярэдне выдаліўшы з кластара ноду з размеркаванымі слотамі. Паколькі дадзеныя ў неразмеркаваных слотаў і так недаступныя, турбавацца аб праблемах з даступнасцю гэтых слотаў ужо позна. У сваю чаргу на размеркаваныя слоты аперацыя не паўплывае.
  • Яшчэ адна карысная аперацыя - monitor. Яна дазваляе ў рэальным часе бачыць увесь спіс запытаў, якія ідуць на ноду. Больш за тое, па ёй можна зрабіць grep і даведацца, ці ёсць патрэбны трафік.

Таксама варта згадаць аб працэдуры аварыйнага пераключэння майстра. Калі сцісла, то яна ёсць, і, на мой погляд, выдатна працуе. Аднак не варта думаць, што калі выдраць шнур з разеткі на машыне з майстар-нодай, Redis тут жа пераключыцца і кліенты не заўважаць страты. На маёй практыцы пераключэнне адбываецца некалькі секунд. На працягу гэтага часу частка дадзеных будзе недаступная: выяўляецца недаступнасць майстра, ноды галасуюць за новага, слейвы перамыкаюцца, дадзеныя сінхранізуюцца. Лепшы спосаб пераканацца самастойна ў тым, што схема працоўная, гэта правесці лакальныя вучэнні. Падніміце кластар на сваім наўтбуку, дайце мінімальную нагрузку, зымітуйце падзенне (напрыклад, заблакаваўшы парты), ацаніце хуткасць пераключэння. На мой погляд, толькі пагуляўшы такім чынам дзень-два, можна быць упэўненым у рабоце тэхналогіі. Ну, ці спадзявацца, што софт, якім карыстаецца палова інтэрнэту, напэўна працуе.

Канфігурацыя

Часцяком, канфігурацыя - першае, што трэба для пачатку працы з інструментам., А калі ўсё зарабіла, канфіг і чапаць не хочацца. Неабходныя пэўныя намаганні, каб прымусіць сябе вярнуцца да налад і старанна іх прошерстить. На маёй памяці ў нас было як мінімум два сур'ёзныя факапы з-за няўважлівасці да канфігурацыі. Звярніце асаблівую ўвагу на наступныя пункты:

  • timeout 0
    Час, праз які зачыняюцца неактыўныя злучэнні (у секундах). 0 - не зачыняюцца
    Не кожная наша бібліятэка ўмела карэктна закрываць злучэнні. Адключыўшы гэтую настройку, мы рызыкуем уперціся ў ліміт па колькасці кліентаў. З іншага боку, калі такая праблема ёсць, то аўтаматычны разрыў страчаных злучэнняў замаскіруе яе, і мы можам не заўважыць. Акрамя таго, не варта ўключаць гэтую настройку пры выкарыстанні persist-злучэнняў.
  • Save xy & appendonly yes
    Захаванне RDB-снепшота.
    Праблемы RDB/AOF мы падрабязна абмяркуем ніжэй.
  • stop-writes-on-bgsave-error no & slave-serve-stale-data yes
    Калі ўключана, то пры паломцы RDB-снепшота майстар перастане прымаць запыты на змену. Калі злучэнне з майстрам страчана, то слейв можа працягваць адказваць на запыты (yes). Ці спыніць адказваць (no)
    Нас не задавальняе сітуацыя, пры якой Redis ператвараецца ў гарбуз.
  • repl-ping-slave-period 5
    Праз гэты прамежак часу мы пачнем турбавацца аб тым, што майстар зламаўся і сітавіна бы правесці працэдуру failover'a.
    Прыйдзецца ўручную знаходзіць баланс паміж ілжывымі спрацоўваннямі і запускам failover'а. На нашай практыцы гэта 5 секунд.
  • repl-backlog-size 1024mb & epl-backlog-ttl 0
    Роўна столькі дадзеных мы можам захоўваць у буферы для якая адвалілася рэплікі. Калі буфер скончыцца, то давядзецца цалкам сінхранізавацца.
    Практыка падказвае, што лепш паставіць значэнне большае. Прычын, па якіх рэпліка можа пачаць адставаць, дастаткова. Калі яна адстае, то, хутчэй за ўсё, ваш майстар ужо з цяжкасцю спраўляецца, а поўная сінхранізацыя стане апошняй кропляй.
  • maxclients 10000
    Максімальная колькасць аднаразовых кліентаў.
    Па нашым досведзе, лепш паставіць значэнне пабольш. Redis выдатна спраўляецца з 10 тысяч злучэнняў. Толькі пераканайцеся, што ў сістэме дастаткова сокетаў.
  • maxmemory-policy volatile-ttl
    Правіла, па якім выдаляюцца ключы пры дасягненні ліміту даступнай памяці.
    Тут важнае не само правіла, а разуменне, як гэта будзе адбывацца. Redis можна пахваліць за ўменне штатна працаваць пры дасягненні ліміту памяці.

Праблемы RDB і AOF

Хаця сам Redis захоўвае ўсю інфармацыю ў аператыўнай памяці, таксама ёсць механізм захавання дадзеных на дыск. А дакладней, тры механізмы:

  • RDB-snapshot - поўны злепак усіх дадзеных. Усталёўваецца з дапамогай канфігурацыі SAVE XY і чытаецца як "Захоўваць поўны снепшот усіх дадзеных кожныя X секунд, калі змянілася хаця б Y ключоў".
  • Append-only file - спіс аперацый у парадку іх выканання. Дадае новыя прыйшэлыя аперацыі ў файл кожныя Х секунд ці кожныя Y аперацый.
  • RDB and AOF - камбінацыя двух папярэдніх.

Ва ўсіх метадаў ёсць свае добрыя якасці і недахопы, я не буду пералічваць іх усё, толькі зверну ўвагі на не відавочныя, на мой погляд, моманты.

Па-першае, для захавання RDB-снепшота патрабуецца выклікаць FORK. Калі дадзеных шмат, гэта можа павесіць увесь Redis на перыяд ад некалькіх мілісекунд да секунды. Акрамя таго, сістэме патрабуецца вылучыць памяць пад такі снепшот, што прыводзіць да неабходнасці трымаць на лагічнай машыне падвойны запас па аператыўнай памяці: калі для Redis выдзелена 8 Гб, то на віртуалцы з ім павінна быць даступна 16.

Па-другое, ёсць праблемы з частковай сінхранізацыяй. У рэжыме AOF пры перападключэнні слейва замест частковай сінхранізацыі можа выконвацца поўная. Чаму так адбываецца, я не здолеў зразумець. Але памятаць аб гэтым варта.

Гэтыя два пункты ўжо прымушаюць задумацца аб тым, а ці так нам патрэбны гэтыя дадзеныя на дыску, калі і так усё дублюецца слейвамі. Страціць дадзеныя можна толькі пры выхадзе са строю ўсіх слейваў, а гэта праблема ўзроўню "пажар у ДЦ". У якасці кампрамісу можна прапанаваць захоўваць дадзеныя толькі на слейвах, але ў гэтым выпадку трэба пераканацца, што гэтыя слейвы ніколі не стануць майстрам пры аварыйным аднаўленні (для гэтага ёсць настройка прыярытэту слейваў у іх канфігу). Для сябе мы ў кожным канкрэтным выпадку думаем над тым, ці трэба захоўваць дадзеныя на дыск, і часцей за ўсё адказваем "не".

Заключэнне

У зняволенні буду спадзявацца, што змог даць агульнае ўяўленне аб рабоце redis-cluster-а тым, хто зусім пра яго не чуў, а таксама звярнуў увагу на нейкія невідавочныя моманты для тых, хто ўжо даўно ім карыстаецца.
Дзякуй за нададзены час і, як звычайна, каментары па тэме вітаюцца.

Крыніца: habr.com

Дадаць каментар