
Venind la un produs care se dezvoltă de mai bine de un deceniu, nu este deloc surprinzător să găsim tehnologii învechite în el. Dar dacă în șase luni trebuie să menții încărcătura de 10 ori mai mare, iar costul căderilor va crește de sute de ori? În acest caz, ai nevoie de un inginer de încărcare mare. Dar în lipsa unei menajere, mi-au încredințat rezolvarea problemei. În prima parte a articolului vă voi spune cum ne-am mutat de la Redis la Redis-cluster, iar în a doua parte vă voi oferi sfaturi despre cum să începeți să utilizați cluster-ul și la ce să acordați atenție atunci când îl utilizați.
Alegerea tehnologiei
E atât de rău? separate Redis (redis autonom) într-o configurație de 1 master și N sclavi? De ce o numesc tehnologie învechită?
Nu, Redis nu este chiar așa de rău... Cu toate acestea, există unele neajunsuri care nu pot fi ignorate.
În primul rând, Redis nu acceptă mecanisme de recuperare în caz de dezastru după o defecțiune principală. Pentru a rezolva această problemă, am folosit o configurație cu transfer automat al VIP-urilor către un nou master, schimbând rolul unuia dintre sclavi și comutându-i pe restul. Acest mecanism a funcționat, dar nu putea fi numit o soluție de încredere. În primul rând, au apărut alarme false și, în al doilea rând, era de unică folosință, iar după operare au fost necesare acțiuni manuale pentru a încărca arcul.
În al doilea rând, a avea un singur maestru a dus la problema sharding-ului. A trebuit să creăm mai multe clustere independente „1 master și N slaves”, apoi să distribuim manual bazele de date între aceste mașini și să sperăm că mâine una dintre bazele de date nu se va umfla atât de mult încât să fie mutată într-o instanță separată.
Care sunt opțiunile?
- Cea mai scumpă și mai bogată soluție este Redis-Enterprise. Aceasta este o soluție în cutie cu suport tehnic complet. În ciuda faptului că arată ideal din punct de vedere tehnic, nu ni s-a potrivit din motive ideologice.
- Redis-cluster. Din cutie există suport pentru master failover și sharding. Interfața nu este aproape deloc diferită de versiunea obișnuită. Pare promițător, vom vorbi despre capcane mai târziu.
- Tarantool, Memcache, Aerospike și altele. Toate aceste instrumente fac cam același lucru. Dar fiecare are propriile neajunsuri. Am decis să nu ne punem toate ouăle într-un singur coș. Folosim Memcache și Tarantool pentru alte sarcini și, privind în viitor, voi spune că în practica noastră au fost mai multe probleme cu ele.
Specificații de utilizare
Să aruncăm o privire la ce probleme am rezolvat istoric cu Redis și ce funcționalitate am folosit:
- Memorați în cache înainte de solicitările către servicii la distanță precum 2GIS | Golang
GET SET MGET MSET "SELECT DB"
- Cache înainte de MYSQL | PHP
GET SET MGET MSET SCAN "KEY BY PATTERN" "SELECT DB"
- Stocarea principală pentru serviciul de lucru cu sesiuni și coordonate șofer | Golang
GET SET MGET MSET „SELECT DB” „ADD GEO KEY” „GET GEO KEY” SCANARE
După cum puteți vedea, nu există matematică superioară. Care este atunci dificultatea? Să ne uităm la fiecare metodă separat.
metodă
Descriere
Caracteristicile Redis-cluster
decizie
FII GATA
Tasta de scriere/citire
MGET MSET
Scrieți/citește mai multe chei
Cheile vor fi pe diferite noduri. Bibliotecile gata făcute pot efectua operații multiple numai într-un singur nod
Înlocuiți MGET cu o conductă de N operațiuni GET
SELECTARE DB
Selectați baza cu care vom lucra
Nu acceptă mai multe baze de date
Pune totul într-o singură bază de date. Adăugați prefixe la chei
SCAN
Treceți prin toate cheile din baza de date
Deoarece avem o singură bază de date, parcurgerea tuturor cheilor din cluster este prea costisitoare
Mențineți un invariant într-o cheie și faceți un HSCAN pe această cheie. Sau refuza complet
GEO
Operații cu geokey
Geokey nu este fragmentat
CHEIE CU MODEL
Căutarea unei chei după model
Deoarece avem o singură bază de date, vom căuta în toate cheile din cluster. Prea scump
Refuzați sau mențineți invariantul, ca în cazul SCAN
Redis vs Redis-cluster
Ce pierdem și ce câștigăm când trecem la un cluster?
- Dezavantaje: pierdem funcționalitatea mai multor baze de date.
- Dacă vrem să stocăm într-un singur cluster date care nu au legătură logic, va trebui să facem cârje sub formă de prefixe.
- Pierdem toate operațiunile „de bază”, cum ar fi SCAN, DBSIZE, CLEAR DB etc.
- Operațiunile multiple au devenit mult mai dificil de implementat, deoarece pot necesita acces la mai multe noduri.
- avantaje:
- Toleranță la erori sub formă de failover principal.
- Sharding pe partea Redis.
- Transferați datele între noduri atomic și fără timp de nefuncționare.
- Adăugați și redistribuiți capacitatea și încărcăturile fără întreruperi.
Aș concluziona că, dacă nu trebuie să oferiți un nivel ridicat de toleranță la erori, atunci mutarea într-un cluster nu merită, deoarece poate fi o sarcină non-trivială. Dar dacă alegeți inițial între o versiune separată și o versiune de cluster, atunci ar trebui să alegeți un cluster, deoarece nu este mai rău și, în plus, vă va scuti de unele dintre durerile de cap.
Pregătirea de a se muta
Să începem cu cerințele pentru mutare:
- Ar trebui să fie fără sudură. O oprire completă a serviciului de 5 minute nu ne convine.
- Ar trebui să fie cât mai sigur și gradual posibil. Vreau să am un anumit control asupra situației. Nu vrem să aruncăm totul dintr-o dată și să ne rugăm pentru butonul de derulare înapoi.
- Pierdere minimă de date la mutare. Înțelegem că va fi foarte dificil să se deplaseze atomic, așa că permitem o oarecare desincronizare între date în Redis obișnuit și în cluster.
Întreținerea clusterului
Chiar înainte de mutare, ar trebui să ne gândim dacă putem sprijini clusterul:
- Diagrame. Folosim Prometheus și Grafana pentru a reprezenta grafic încărcarea procesorului, utilizarea memoriei, numărul de clienți, numărul de operațiuni GET, SET, AUTH etc.
- Expertiză. Imaginează-ți că mâine vei avea un grup uriaș sub responsabilitatea ta. Dacă se rupe, nimeni în afară de tine nu o poți repara. Dacă începe să încetinească, toată lumea va alerga spre tine. Dacă trebuie să adăugați resurse sau să redistribuiți încărcarea, reveniți la dvs. Pentru a nu deveni gri la 25 de ani, este indicat să asigurați aceste cazuri și să verificați dinainte cum se va comporta tehnologia în cadrul anumitor acțiuni. Să vorbim despre asta mai detaliat în secțiunea „Expertă”.
- Monitorizare și alerte. Când un cluster se defectează, vrei să fii primul care știe despre el. Aici ne-am limitat la o notificare că toate nodurile returnează aceleași informații despre starea clusterului (da, se întâmplă diferit). Iar alte probleme pot fi observate mai rapid prin alertele de la serviciile pentru clienți Redis.
trecere
Cum ne vom mișca:
- În primul rând, trebuie să pregătiți o bibliotecă pentru a lucra cu clusterul. Am luat go-redis ca bază pentru versiunea Go și am schimbat-o puțin pentru a ne potrivi. Am implementat Multi-metode prin conducte și, de asemenea, am corectat ușor regulile pentru solicitările repetate. Versiunea PHP a avut mai multe probleme, dar în cele din urmă ne-am stabilit pe php-redis. Au introdus recent suportul pentru cluster și arată bine în opinia noastră.
- Apoi, trebuie să implementați clusterul în sine. Acest lucru se face literalmente în două comenzi bazate pe fișierul de configurare. Vom discuta despre setare mai detaliat mai jos.
- Pentru mișcarea treptată folosim modul uscat. Deoarece avem două versiuni ale bibliotecii cu aceeași interfață (una pentru versiunea obișnuită, cealaltă pentru cluster), nu costă nimic să creăm un wrapper care să funcționeze cu o versiune separată și, în paralel, să dubleze toate cererile către cluster, comparați răspunsurile și scrieți discrepanțe în jurnale (în cazul nostru în NewRelic). Astfel, chiar dacă versiunea cluster se întrerupe în timpul lansării, producția noastră nu va fi afectată.
- După ce am lansat clusterul în modul uscat, putem privi cu calm graficul discrepanțelor de răspuns. Dacă rata de eroare se mișcă încet, dar sigur către o constantă mică, atunci totul este bine. De ce există încă discrepanțe? Deoarece înregistrarea într-o versiune separată are loc puțin mai devreme decât în cluster și din cauza microlag-ului, datele pot diverge. Rămâne doar să ne uităm la jurnalele de discrepanțe, iar dacă toate sunt explicate prin non-atomicitatea înregistrării, atunci putem merge mai departe.
- Acum puteți comuta modul uscat în direcția opusă. Vom scrie și citi din cluster și îl vom duplica într-o versiune separată. Pentru ce? În săptămâna următoare, aș dori să observ munca grupului. Dacă se dovedește brusc că există probleme la sarcina de vârf sau nu am ținut cont de ceva, avem întotdeauna o revenire de urgență la vechiul cod și datele actuale datorită modului uscat.
- Tot ce rămâne este să dezactivați modul uscat și să demontați versiunea separată.
Expertiză
În primul rând, pe scurt despre designul clusterului.
În primul rând, Redis este un magazin cheie-valoare. Șirurile arbitrare sunt folosite ca chei. Numerele, șirurile și structurile întregi pot fi folosite ca valori. Există foarte multe dintre acestea din urmă, dar pentru înțelegerea structurii generale acest lucru nu este important pentru noi.
Următorul nivel de abstractizare după chei este sloturile (SLOTS). Fiecare cheie aparține unuia dintre cele 16 de sloturi. În fiecare slot poate exista orice număr de chei. Astfel, toate cheile sunt împărțite în 383 de seturi disjunse.

În continuare, trebuie să existe N noduri master în cluster. Fiecare nod poate fi gândit ca o instanță Redis separată care știe totul despre alte noduri din cluster. Fiecare nod master conține un număr de sloturi. Fiecare slot aparține unui singur nod master. Toate sloturile trebuie să fie distribuite între noduri. Dacă unele sloturi nu sunt alocate, atunci cheile stocate în ele vor fi inaccesibile. Este logic să rulați fiecare nod master pe o mașină logică sau fizică separată. De asemenea, merită să ne amintim că fiecare nod rulează doar pe un nucleu și, dacă doriți să rulați mai multe instanțe Redis pe aceeași mașină logică, asigurați-vă că rulează pe nuclee diferite (nu am încercat acest lucru, dar în teorie ar trebui să funcționeze) . În esență, nodurile master oferă sharding regulat, iar mai multe noduri master permit cererilor de scriere și citire la scară.
După ce toate cheile sunt distribuite între sloturi, iar sloturile sunt împrăștiate printre nodurile master, un număr arbitrar de noduri slave poate fi adăugat la fiecare nod master. În cadrul fiecărei astfel de legături master-slave, replicarea normală va funcționa. Sunt necesari slave pentru a scala cererile de citire și pentru failover în caz de defecțiune a masterului.

Acum să vorbim despre operațiuni pe care ar fi mai bine să le poți face.
Vom accesa sistemul prin Redis-CLI. Deoarece Redis nu are un singur punct de intrare, puteți efectua următoarele operații pe oricare dintre noduri. În fiecare punct atrag separat atenția asupra posibilității de a efectua operația sub sarcină.
- Primul și cel mai important lucru de care avem nevoie este operarea nodurilor cluster. Returnează starea clusterului, arată o listă de noduri, rolurile acestora, distribuția sloturilor etc. Mai multe informații pot fi obținute folosind informații despre cluster și sloturi pentru cluster.
- Ar fi bine să puteți adăuga și elimina noduri. În acest scop, există operațiuni de întâlnire a clusterului și de uitare a clusterului. Vă rugăm să rețineți că uitarea clusterului trebuie aplicată FIECARE nod, atât master, cât și replici. Și întâlnirea clusterului trebuie apelată doar pe un singur nod. Această diferență poate fi deconcertantă, așa că cel mai bine este să învățați despre ea înainte de a intra live cu clusterul dvs. Adăugarea unui nod se face în siguranță în luptă și nu afectează în niciun fel funcționarea clusterului (ceea ce este logic). Dacă intenționați să eliminați un nod din cluster, ar trebui să vă asigurați că nu au mai rămas sloturi pe el (altfel riscați să pierdeți accesul la toate cheile de pe acest nod). De asemenea, nu ștergeți un master care are sclavi, altfel se va efectua un vot inutil pentru un nou master. Dacă nodurile nu mai au sloturi, atunci aceasta este o mică problemă, dar de ce avem nevoie de opțiuni suplimentare dacă putem șterge mai întâi sclavii.
- Dacă trebuie să schimbați forțat pozițiile master și slave, atunci comanda de failover a clusterului va funcționa. Când îl chemați în luptă, trebuie să înțelegeți că maestrul nu va fi disponibil în timpul operațiunii. De obicei, comutarea are loc în mai puțin de o secundă, dar nu este atomică. Vă puteți aștepta ca unele solicitări către comandant să eșueze în acest timp.
- Înainte de a elimina un nod din cluster, nu ar trebui să rămână sloturi pe el. Este mai bine să le redistribuiți folosind comanda cluster reshard. Sloturile vor fi transferate de la un master la altul. Întreaga operațiune poate dura câteva minute, depinde de volumul de date transferate, dar procesul de transfer este sigur și nu afectează în niciun fel funcționarea cluster-ului. Astfel, toate datele pot fi transferate de la un nod la altul direct sub sarcină și fără a vă face griji cu privire la disponibilitatea acestora. Cu toate acestea, există și subtilități. În primul rând, transferul de date este asociat cu o anumită sarcină asupra nodurilor destinatarului și expeditorului. Dacă nodul destinatar este deja încărcat puternic pe procesor, atunci nu ar trebui să îl încărcați cu primirea de date noi. În al doilea rând, de îndată ce nu mai rămâne niciun slot pe masterul care trimite, toți sclavii săi vor merge imediat la masterul la care au fost transferate aceste sloturi. Și problema este că toți acești sclavi vor dori să sincronizeze datele deodată. Și vei fi norocos dacă este mai degrabă o sincronizare parțială decât completă. Luați în considerare acest lucru și combinați operațiunile de transfer de sloturi și dezactivare/transfer slave. Sau sperați că aveți o marjă suficientă de siguranță.
- Ce ar trebui să faci dacă, în timpul transferului, descoperi că ți-ai pierdut sloturile undeva? Sper că această problemă nu vă afectează, dar dacă o face, există o operație de remediere a clusterului. Cel puțin, ea va împrăștia sloturile peste noduri într-o ordine aleatorie. Recomand să verificați funcționarea acestuia prin eliminarea mai întâi a nodului cu sloturi distribuite din cluster. Deoarece datele din sloturile nealocate sunt deja indisponibile, este prea târziu să vă faceți griji cu privire la problemele legate de disponibilitatea acestor sloturi. La rândul său, operațiunea nu va afecta sloturile distribuite.
- O altă operațiune utilă este monitorul. Vă permite să vedeți în timp real întreaga listă de solicitări care ajung la nod. Mai mult, poți să-l grepezi și să afli dacă există traficul necesar.
De asemenea, merită menționată procedura master failover. Pe scurt, există și, după părerea mea, funcționează grozav. Cu toate acestea, nu credeți că, dacă deconectați cablul de alimentare la o mașină cu un nod master, Redis va comuta imediat și clienții nu vor observa pierderea. În practica mea, comutarea are loc în câteva secunde. În acest timp, unele dintre date vor fi indisponibile: indisponibilitatea masterului este detectată, nodurile votează pentru unul nou, sclavii sunt comutați, datele sunt sincronizate. Cel mai bun mod de a vă asigura că schema funcționează este să efectuați exerciții locale. Ridicați cluster-ul de pe laptopul dvs., acordați-i o sarcină minimă, simulați o prăbușire (de exemplu, blocând porturile) și evaluați viteza de comutare. După părerea mea, doar după ce ai jucat în acest fel o zi sau două poți fi încrezător în funcționarea tehnologiei. Ei bine, sau sper că software-ul pe care îl folosește jumătate din Internet probabil funcționează.
configurație
Adesea, configurația este primul lucru de care aveți nevoie pentru a începe să lucrați cu instrumentul și, când totul funcționează, nici nu doriți să atingeți configurația. Este nevoie de ceva efort pentru a vă forța să reveniți la setări și să le parcurgeți cu atenție. În memoria mea, am avut cel puțin două eșecuri grave din cauza neatenției la configurație. Acordați o atenție deosebită următoarelor puncte:
- timeout 0
Timp după care conexiunile inactive sunt închise (în secunde). 0 - nu închide
Nu fiecare bibliotecă a noastră a reușit să închidă corect conexiunile. Dezactivând această setare, riscăm să atingem limita numărului de clienți. Pe de altă parte, dacă există o astfel de problemă, atunci încetarea automată a conexiunilor pierdute o va masca și este posibil să nu observăm. În plus, nu ar trebui să activați această setare atunci când utilizați conexiuni persistente. - Salvați xy și numai da
Salvarea unui instantaneu RDB.
Vom discuta problemele RDB/AOF în detaliu mai jos. - stop-writes-on-bgsave-error nu și slave-serve-stale-data da
Dacă este activată, dacă instantaneul RDB se întrerupe, masterul va înceta să accepte cereri de modificare. Dacă conexiunea la master este pierdută, slave poate continua să răspundă la solicitări (da). Sau nu va mai răspunde (nu)
Nu suntem multumiti de situatia in care Redis se transforma intr-un dovleac. - repl-ping-slave-perioada 5
După această perioadă de timp, vom începe să ne îngrijorăm că masterul s-a defectat și este timpul să efectuăm procedura de failover.
Va trebui să găsiți manual un echilibru între false pozitive și declanșarea unui failover. În practica noastră, aceasta este de 5 secunde. - repl-backlog-size 1024mb și epl-backlog-ttl 0
Putem stoca exact atât de multe date într-un buffer pentru o replică eșuată. Dacă tamponul se epuizează, va trebui să vă sincronizați complet.
Practica sugerează că este mai bine să setați o valoare mai mare. Există o mulțime de motive pentru care o replică ar putea începe să întârzie. Dacă rămâne în urmă, atunci cel mai probabil stăpânul tău se luptă deja să facă față, iar sincronizarea completă va fi ultima picătură. - maxclienti 10000
Număr maxim de clienți unici.
Din experiența noastră, este mai bine să setăm o valoare mai mare. Redis gestionează bine 10 conexiuni. Doar asigurați-vă că există suficiente prize pe sistem. - maxmemory-policy volatile-ttl
Regula prin care cheile sunt șterse atunci când limita de memorie disponibilă este atinsă.
Ceea ce este important aici nu este regula în sine, ci înțelegerea modului în care se va întâmpla acest lucru. Redis poate fi lăudat pentru capacitatea sa de a funcționa normal atunci când este atinsă limita de memorie.
Probleme RDB și AOF
Deși Redis în sine stochează toate informațiile în RAM, există și un mecanism pentru salvarea datelor pe disc. Mai exact, trei mecanisme:
- RDB-snapshot - un instantaneu complet al tuturor datelor. Setați folosind configurația SAVE XY și scrie „Salvați un instantaneu complet al tuturor datelor la fiecare X secunde dacă cel puțin Y tastele s-au schimbat”.
- Fișier numai pentru atașare - o listă de operațiuni în ordinea în care sunt efectuate. Adaugă noi operațiuni de intrare în fișier la fiecare X secunde sau la fiecare Y operațiuni.
- RDB și AOF sunt o combinație a celor două anterioare.
Toate metodele au avantajele și dezavantajele lor, nu le voi enumera pe toate, voi atrage atenția doar asupra unor puncte care, în opinia mea, nu sunt evidente.
În primul rând, salvarea unui instantaneu RDB necesită apelarea FORK. Dacă există o mulțime de date, acest lucru poate bloca întregul Redis pentru o perioadă de la câteva milisecunde până la o secundă. În plus, sistemul trebuie să aloce memorie pentru un astfel de instantaneu, ceea ce duce la necesitatea păstrării unei surse duble de RAM pe mașina logică: dacă sunt alocați 8 GB pentru Redis, atunci 16 GB ar trebui să fie disponibili pe mașina virtuală cu aceasta.
În al doilea rând, există probleme cu sincronizarea parțială. În modul AOF, când slave este reconectat, în loc de sincronizare parțială, poate fi efectuată sincronizarea completă. De ce se întâmplă asta, nu am putut înțelege. Dar merită să ne amintim asta.
Aceste două puncte deja ne fac să ne gândim dacă avem cu adevărat nevoie de aceste date de pe disc dacă totul este deja duplicat de sclavi. Datele pot fi pierdute numai dacă toți sclavii eșuează, iar aceasta este o problemă de nivel „incendiu în DC”. Ca un compromis, puteți propune să salvați datele numai pe slave, dar în acest caz trebuie să vă asigurați că acești slave nu vor deveni niciodată master în timpul recuperării în caz de dezastru (pentru aceasta există o setare de prioritate slave în configurația lor). Pentru noi înșine, în fiecare caz specific ne gândim dacă este necesar să salvăm datele pe disc și cel mai adesea răspunsul este „nu”.
Concluzie
În concluzie, sper că am putut să dau o idee generală despre cum funcționează redis-cluster pentru cei care nu au auzit deloc de el și, de asemenea, am atras atenția asupra unor puncte neevidente pentru cei care l-au folosit. pentru o lungă perioadă de timp.
Vă mulțumim pentru timpul acordat și, ca întotdeauna, comentariile pe această temă sunt binevenite.
Sursa: www.habr.com
