
NÄr man kommer til et produkt som har vÊrt under utvikling i over et tiÄr, er det slett ikke overraskende Ä finne utdaterte teknologier i det. Men hva om du om seks mÄneder mÄ stÞtte en last som er 10 ganger hÞyere, og kostnadene ved feil Þker hundrevis av ganger? I dette tilfellet trenger du en kul Highload Engineer. Men pÄ grunn av mangelen pÄ en slik tjenestepike ble jeg betrodd Ä lÞse problemet. I den fÞrste delen av artikkelen vil jeg fortelle deg hvordan vi gikk fra Redis til Redis-klyngen, og i den andre delen vil jeg gi rÄd om hvordan du begynner Ä bruke klyngen og hva du bÞr vÊre oppmerksom pÄ under drift.
Teknologivalg
Er det virkelig sÄ ille? separate Redis (frittstÄende redis) i 1 master- og N slavekonfigurasjon? Hvorfor kaller jeg det eldre teknologi?
Nei, Redis er ikke sÄ ille ... Det er imidlertid noen mangler som ikke kan ignoreres.
For det fÞrste stÞtter ikke Redis mekanismer for nÞdgjenoppretting etter at masteren krasjer. For Ä lÞse dette problemet brukte vi en konfigurasjon med automatisk overfÞring av VIP-er til en ny master, endring av rollen til en av slavene og bytte av de andre. Denne mekanismen fungerte, men den kunne ikke kalles en pÄlitelig lÞsning. For det fÞrste var det falske positiver, og for det andre var det en engangsoperasjon, og etter utlÞsningen var det nÞdvendig med manuelle handlinger for Ä spenne fjÊren.
For det andre fÞrte det til problemet med sharding at man bare hadde én master. Det var nÞdvendig Ä opprette flere uavhengige klynger med "1 master og N slaver", deretter distribuere databasene manuelt mellom disse maskinene og hÄpe at en av databasene i morgen ikke vil svulme sÄ mye at den mÄ flyttes til en egen instans.
Hva er alternativene?
- Den dyreste og mest omfattende lÞsningen er Redis-Enterprise. Det er en bokslÞsning med full teknisk stÞtte. Til tross for at den ser ideell ut fra et teknisk synspunkt, passet den ikke oss av ideologiske Ärsaker.
- Redis-klynge. StĂžtte for master failover og sharding er tilgjengelig rett ut av esken. Grensesnittet er nesten det samme som den vanlige versjonen. Ser lovende ut, vi skal snakke om fallgruvene senere.
- Tarantool, Memcache, Aerospike og andre. Alle disse verktÞyene gjÞr omtrent det samme. Men hver har sine egne ulemper. Vi bestemte oss for Ä ikke legge alle eggene i én kurv. Vi bruker Memcache og Tarantool til andre oppgaver, og nÄr jeg ser fremover, vil jeg si at det i vÄr praksis var flere problemer med dem.
Spesifikasjoner for bruk
La oss ta en titt pÄ hvilke oppgaver vi historisk sett har lÞst med Redis og hvilken funksjonalitet vi har brukt:
- Bufre fĂžr forespĂžrsler til eksterne tjenester som 2GIS | Golang
HENT SET MGET MSET "VELG DB"
- Hurtigbuffer fĂžr MYSQL | PHP
FĂ INNSTILLING MGET MSET SKANN "NĂKKEL ETTER MĂNSTER" "VELG DB"
- Hovedlagring for tjenesten for arbeid med Þkter og koordinater for sjÄfÞrer | Golang
HENT ANGI MG HENT MSETT "VELG DB" "LEGG TIL GEO-NĂKKEL" "HENT GEO-NĂKKEL" SKANNING
Som du ser, ingen hÞyere matematikk. Hva er vanskelighetsgraden da? La oss se pÄ hver metode separat.
metode
beskrivelse
Funksjoner i Redis-klyngen
beslutning
GJĂR DEG KLAR
Skrive-/lesenĂžkkel
MGET MSET
Skriv/les flere nĂžkler
NÞklene vil vÊre pÄ forskjellige noder. Ferdige biblioteker kan bare utfÞre fleroperasjoner innenfor én node.
Erstatt MGET med en pipeline av N GET-operasjoner
VELG DB
Velg databasen vi skal jobbe med
StĂžtter ikke flere databaser
Sett alt i én database. Legg til prefikser til nÞkler.
SCAN
GĂ„ gjennom alle nĂžklene i databasen
Siden vi har én database, er det for dyrt Ä gÄ gjennom alle nÞklene i klyngen.
Behold invarianten innenfor én nÞkkel og utfÞr HSCAN pÄ denne nÞkkelen. Eller avvis den helt.
GEO
Geokey-operasjoner
Geokey er ikke shardet
NĂKKEL ETTER MĂNSTER
SĂžk etter en nĂžkkel etter mĂžnster
Siden vi har én database, vil vi sÞke etter alle nÞklene i klyngen. For dyrt.
Avvis eller stĂžtte invarianten, som i tilfellet med SCAN
Redis vs. Redis-klynge
Hva taper vi og hva vinner vi nÄr vi bytter til en klynge?
- Ulemper: vi mister funksjonaliteten til flere databaser.
- Hvis vi Þnsker Ä lagre logisk urelaterte data i én klynge, mÄ vi lage krykker i form av prefikser.
- Vi mister alle operasjoner «pÄ databasen», som SCAN, DBSIZE, CLEAR DB, osv.
- Multioperasjoner har blitt betydelig vanskeligere Ă„ implementere fordi de kan kreve tilgang til flere noder.
- fordeler:
- Feiltoleranse i form av master-failover.
- Sharding pÄ Redis-siden.
- OverfĂžr data mellom noder atomisk og uten nedetid.
- Legge til og omfordele kapasitet og last uten nedetid.
Jeg vil konkludere med at hvis du ikke trenger Ä tilby et hÞyt nivÄ av feiltoleranse, er det ikke verdt Ä gÄ over til en klynge, siden dette kan vÊre en ikke-triviell oppgave. Men hvis du i utgangspunktet velger mellom en separat versjon og en klynge, bÞr du velge en klynge, siden den ikke er verre og i tillegg vil lindre deg for noen hodepiner.
Forbereder seg pÄ Ä flytte
La oss starte med kravene for flytting:
- Det skal vÊre sÞmlÞst. En fullstendig stopp i servicen pÄ 5 minutter er ikke akseptabelt for oss.
- Det bÞr vÊre sÄ trygt og gradvis som mulig. Vi Þnsker Ä ha en viss kontroll over situasjonen. Vi Þnsker ikke Ä drikke alt pÄ en gang og bare be om tilbakerullingsknappen.
- Minimalt datatap under migrering. Vi forstÄr at det vil vÊre svÊrt vanskelig Ä migrere atomisk, sÄ vi tillater noe desynkronisering mellom data i vanlig og klynget Redis.
Klyngevedlikehold
FÞr vi flytter, bÞr vi tenke pÄ om vi kan stÞtte klyngen:
- Grafer. Vi bruker Prometheus og Grafana til Ă„ lage grafer for CPU-belastning, minnebruk, antall klienter, antall GET-, SET- og AUTH-operasjoner osv.
- Ekspertise. Tenk deg at du i morgen vil vÊre ansvarlig for en enorm klynge. Hvis den gÄr i stykker, er det ingen andre enn deg som kan fikse den. Hvis den begynner Ä sakke ned, vil alle lÞpe til deg. Hvis du trenger Ä legge til ressurser eller omfordele belastningen, vil de komme til deg igjen. For ikke Ä bli grÄ som 25-Äring, er det lurt Ä forutse disse tilfellene og sjekke pÄ forhÄnd hvordan teknologien vil oppfÞre seg under visse handlinger. Vi vil snakke mer detaljert om dette i avsnittet "Ekspertise".
- OvervÄking og varsler. NÄr en klynge slutter Ä virke, vil du vÊre den fÞrste til Ä vite om det. Her har vi begrenset oss til et varsel om at alle noder returnerer den samme informasjonen om klyngetilstanden (ja, det kan vÊre forskjellig). Andre problemer er raskere Ä oppdage fra varslene til Redis-klienttjenestene.
kryssing
Hvordan vi skal bevege oss:
- FÞrst og fremst mÄ vi forberede et bibliotek for Ä jobbe med en klynge. Vi tok go-redis som grunnlag for Go-versjonen og modifiserte det litt for oss selv. Vi implementerte multimetoder via pipelines, og justerte ogsÄ reglene for gjentatte forespÞrsler litt. Det var flere problemer med PHP-versjonen, men til slutt bestemte vi oss for php-redis. De implementerte nylig klyngestÞtte, og etter vÄr mening ser det bra ut.
- Deretter mÄ du distribuere selve klyngen. Dette gjÞres bokstavelig talt i to kommandoer basert pÄ konfigurasjonsfilen. Vi vil diskutere oppsettet mer detaljert nedenfor.
- For en gradvis migrering bruker vi tÞrrmodus. Siden vi har to versjoner av biblioteket med samme grensesnitt (én for den vanlige versjonen, den andre for klyngen), er det enkelt Ä lage en wrapper som fungerer med en separat versjon og samtidig dupliserer alle forespÞrsler til klyngen, sammenligner svar og skriver avvik til logger (i vÄrt tilfelle til NewRelic). Dermed, selv om klyngeversjonen skulle bryte sammen under utrullingen, vil ikke produksjonen vÄr bli pÄvirket.
- Etter Ä ha rullet ut klyngen i tÞrrmodus, kan vi rolig se pÄ grafen over responsavvik. Hvis andelen feil sakte, men sikkert beveger seg mot en liten konstant, er alt i orden. Hvorfor er det avvik likevel? Fordi registreringen i en separat versjon skjer noe tidligere enn i klyngen, og pÄ grunn av mikroforsinkelsen kan dataene avvike. Alt som gjenstÄr er Ä se pÄ avviksloggene, og hvis alle kan forklares med registreringens ikke-atomisitet, kan vi gÄ videre.
- NĂ„ kan vi bytte tĂžrrmodus i motsatt retning. Vi vil skrive og lese fra klyngen, og duplisere i en separat versjon. Hvorfor? I lĂžpet av den neste uken Ăžnsker vi Ă„ observere klyngens drift. Hvis det plutselig viser seg at det er problemer ved toppbelastning, eller vi ikke har tatt hensyn til noe, har vi alltid en nĂždrollback til den gamle koden og oppdaterte data takket vĂŠre tĂžrrmodus.
- Alt som gjenstÄr er Ä deaktivere tÞrrmodus og avinstallere den separate versjonen.
Ekspertise
FĂžrst en kort oversikt over klyngestrukturen.
FÞrst og fremst er Redis et nÞkkel-verdi-lager. VilkÄrlige strenger brukes som nÞkler. Tall, strenger og hele strukturer kan brukes som verdier. Det finnes mange av de sistnevnte, men dette er ikke viktig for at vi skal forstÄ den generelle strukturen.
Det neste abstraksjonsnivÄet etter nÞkler er spor (SLOTS). Hver nÞkkel tilhÞrer en av 16 383 spor. Innenfor hver spor kan det vÊre et hvilket som helst antall nÞkler. Dermed er alle nÞkler delt inn i 16 383 disjunkte sett.

Deretter bÞr det vÊre N masternoder i klyngen. Hver node kan betraktes som en separat Redis-instans som vet alt om de andre nodene i klyngen. Hver masternode inneholder et visst antall spor. Hvert spor tilhÞrer bare én masternode. Alle spor mÄ fordeles mellom noder. Hvis noen spor ikke er fordelt, vil nÞklene som er lagret i dem vÊre utilgjengelige. Det er fornuftig Ä kjÞre hver masternode pÄ en separat logisk eller fysisk maskin. Det er ogsÄ verdt Ä huske at hver node bare kjÞrer pÄ én kjerne, og hvis du vil kjÞre flere Redis-instanser pÄ én logisk maskin, mÄ du sÞrge for at de kjÞrer pÄ forskjellige kjerner (vi har ikke prÞvd dette, men i teorien bÞr alt fungere). I hovedsak gir masternoder regelmessig sharding, og et stÞrre antall masternoder lar deg skalere skrive- og leseforespÞrsler.
NÄr alle nÞklene er fordelt pÄ tvers av spor, og sporene er fordelt pÄ tvers av masternoder, kan et hvilket som helst antall slavenoder legges til hver masternode. Regelmessig replikering vil operere innenfor hver slik master-slave-kobling. Slaver er nÞdvendige for Ä skalere leseforespÞrsler og for nÞdbytte i tilfelle masterfeil.

La oss nÄ snakke om operasjoner som det ville vÊre bedre Ä kunne utfÞre.
Vi vil fÄ tilgang til systemet via Redis-CLI. Siden Redis ikke har et enkelt inngangspunkt, kan fÞlgende operasjoner utfÞres pÄ hvilken som helst av nodene. I hvert punkt vil jeg separat gjÞre oppmerksom pÄ muligheten for Ä utfÞre operasjonen under belastning.
- Det fÞrste og viktigste vi trenger er operasjonen for klyngenoder. Den returnerer klyngens tilstand, viser listen over noder, deres roller, plassfordeling osv. Ytterligere informasjon kan fÄs ved Ä bruke klyngeinfo og klyngeplasser.
- Det hadde vÊrt fint Ä kunne legge til og fjerne noder. Det finnes cluster meet- og cluster forget-operasjoner for dette. Merk at cluster forget mÄ brukes pÄ HVER node, bÄde mastere og replikaer. Og cluster meet trenger bare Ä kalles pÄ én node. Denne forskjellen kan vÊre forvirrende, sÄ det er bedre Ä vite om den fÞr du setter clusteren i produksjon. à legge til en node gjÞres trygt i kamp og pÄvirker ikke driften av clusteren pÄ noen mÄte (noe som er logisk). Hvis du skal fjerne en node fra clusteren, bÞr du sÞrge for at det ikke er noen spor igjen pÄ den (ellers risikerer du Ä miste tilgang til alle nÞkler pÄ denne noden). Ikke fjern en master som har slaver, ellers vil det bli en unÞdvendig avstemning om en ny master. Hvis det ikke er noen spor pÄ nodene, er dette et lite problem, men hvorfor trenger vi ekstra valg hvis vi fÞrst kan fjerne slavene.
- Hvis du mĂ„ tvinge master og slave til Ă„ bytte, vil cluster failover-kommandoen fungere. NĂ„r du kaller den i kamp, ââmĂ„ du vĂŠre klar over at masteren vil vĂŠre utilgjengelig under operasjonen. Vanligvis skjer byttet pĂ„ under et sekund, men ikke atomĂŠrt. Du kan forvente at noen forespĂžrsler til masteren vil ende med en feil i lĂžpet av denne tiden.
- FÞr du sletter en node fra en klynge, bÞr det ikke vÊre noen spor igjen pÄ den. Det er bedre Ä omfordele dem ved hjelp av cluster reshard-kommandoen. Sporene vil bli overfÞrt fra en master til en annen. Hele operasjonen kan ta flere minutter, avhengig av mengden data som overfÞres, men overfÞringsprosessen er trygg og pÄvirker ikke driften av klyngen pÄ noen mÄte. Dermed kan alle data overfÞres fra en node til en annen direkte under belastning, og du trenger ikke Ä bekymre deg for tilgjengeligheten deres. Det er imidlertid noen finesser. For det fÞrste er dataoverfÞring forbundet med en viss belastning pÄ mottaker- og avsendernodene. Hvis mottakernoden allerede er tungt belastet nÄr det gjelder prosessor, bÞr du ikke laste den med Ä motta nye data. For det andre, sÄ snart det ikke er noen spor igjen pÄ avsendermasteren, vil alle slavene umiddelbart gÄ til masteren som disse sporene ble overfÞrt til. Og problemet er at alle disse slavene vil Þnske Ä synkronisere dataene samtidig. Og du vil vÊre heldig hvis det er delvis synkronisering, ikke full synkronisering. Ta hensyn til dette, og kombiner sporoverfÞringsoperasjoner med slavefrakobling/overfÞring. Eller hÄpe at du har en tilstrekkelig sikkerhetsmargin.
- Hva skal du gjÞre hvis du oppdager at du har mistet spor et sted under overfÞringen? ForhÄpentligvis vil ikke dette problemet pÄvirke deg, men hvis det gjÞr det, er det klyngereparasjonsoperasjonen. Den vil i beste fall fordele spor pÄ tvers av noder i en tilfeldig rekkefÞlge. Jeg anbefaler Ä sjekke driften ved fÞrst Ä slette noden med distribuerte spor fra klyngen. Siden dataene i udistribuerte spor allerede er utilgjengelige, er det for sent Ä bekymre seg for problemer med tilgjengeligheten av disse sporene. Operasjonen vil igjen ikke pÄvirke distribuerte spor.
- En annen nyttig operasjon er monitor. Den lar deg se hele listen over forespÞrsler som gÄr til noden i sanntid. Dessuten kan du grepe den og finne ut om det er nÞdvendig trafikk.
Det er ogsÄ verdt Ä nevne master failover-prosedyren. Kort sagt, den finnes, og etter min mening fungerer den utmerket. Du bÞr imidlertid ikke tro at hvis du trekker ut stÞpselet til maskinen med masternoden, vil Redis umiddelbart bytte over, og klientene vil ikke merke tapet. Etter min erfaring tar byttet noen sekunder. I lÞpet av denne tiden vil noen data vÊre utilgjengelige: masteren oppdages som utilgjengelig, nodene stemmer for en ny, slavene bytter over, og dataene synkroniseres. Den beste mÄten Ä sikre at ordningen fungerer pÄ, er Ä utfÞre lokale Þvelser. Start en klynge pÄ den bÊrbare datamaskinen din, gi den en minimumsbelastning, simuler et fall (for eksempel ved Ä blokkere porter), og evaluer byttehastigheten. Etter min mening kan du bare vÊre sikker pÄ at teknologien fungerer etter Ä ha eksperimentert slik i en dag eller to. Vel, eller hÄpe at programvaren som halve Internett bruker sannsynligvis fungerer.
Konfigurasjon
Konfigurasjon er ofte det fÞrste du trenger for Ä begynne Ä jobbe med et verktÞy. Og nÄr alt fungerer, vil du ikke rÞre konfigurasjonen. Det krever litt innsats Ä tvinge deg selv til Ä gÄ tilbake til innstillingene og gÄ grundig gjennom dem. Jeg husker minst to alvorlige feil pÄ grunn av manglende oppmerksomhet til konfigurasjonen. VÊr spesielt oppmerksom pÄ fÞlgende punkter:
- timeout 0
Tiden det tar fĂžr inaktive tilkoblinger lukkes (i sekunder). 0 - ikke lukket
Ikke alle bibliotekene vi har klarte Ä lukke tilkoblinger riktig. Ved Ä deaktivere denne innstillingen risikerer vi Ä stÞte pÄ grensen for antall klienter. Hvis et slikt problem derimot eksisterer, vil automatisk avslutning av tapte tilkoblinger maskere det, og vi legger kanskje ikke merke til det. I tillegg bÞr du ikke aktivere denne innstillingen nÄr du bruker vedvarende tilkoblinger. - Lagre xy og bare legge til ja
Lagrer RDB-Ăžyeblikksbilde.
Vi vil diskutere RDB/AOF-problemene i detalj nedenfor. - stopp-skriver-pÄ-bgsave-feil nei og slave-serve-stale-data ja
Hvis aktivert, vil masteren slutte Ä godta endringsforespÞrsler hvis RDB-snapshotet er Þdelagt. Hvis forbindelsen til masteren brytes, kan slaven fortsette Ä svare pÄ forespÞrsler (ja). Eller den vil slutte Ä svare (nei).
Vi er ikke fornĂžyde med situasjonen der Redis forvandles til et gresskar. - repl-ping-slave-periode 5
Etter denne perioden vil vi begynne Ä bekymre oss for at masteren har brutt sammen, og at det er pÄ tide Ä utfÞre en failover-prosedyre.
Du mÄ manuelt finne en balanse mellom falske positiver og Ä starte en failover. Etter vÄr erfaring er dette 5 sekunder. - repl-backlog-stÞrrelse 1024 MB og epl-backlog-ttl 0
Vi kan lagre akkurat sÄ mye data i bufferen for en mislykket replika. Hvis bufferen gÄr tom, mÄ vi synkronisere fullstendig.
Erfaring viser at det er bedre Ä sette en hÞyere verdi. Det er mange grunner til at en replika kan begynne Ä ha dÄrlig tid. Hvis den har dÄrlig tid, er det mest sannsynlig at masteren din allerede sliter med Ä takle det, og full synkronisering vil vÊre drÄpen som fÄr begeret til Ä renne over. - maksklienter 10000
Maksimalt antall samtidige klienter.
Etter vÄr erfaring er det bedre Ä sette en hÞyere verdi. Redis hÄndterer 10K-tilkoblinger helt fint. Bare sÞrg for at du har nok sockets i systemet ditt. - maksminnepolicy volatile-ttl
Regelen som bruker for Ä slette nÞkler nÄr den tilgjengelige minnegrensen er nÄdd.
Det som er viktig her er ikke selve regelen, men forstÄelsen av hvordan det vil skje. Redis kan roses for sin evne til Ä fungere normalt nÄr minnegrensen er nÄdd.
RDB- og AOF-problemer
Selv om Redis lagrer all informasjon i RAM, finnes det ogsÄ en mekanisme for Ä lagre data pÄ disk. Mer presist, tre mekanismer:
- RDB-snapshot â et fullstendig snapshot av alle data. Settes med SAVE XY-konfigurasjonen og leses som «Lagre et fullstendig snapshot av alle data hvert X sekund hvis minst Y nĂžkler har endret seg.»
- Tilleggsfil â en liste over operasjoner i den rekkefĂžlgen de utfĂžres. Legger til nye innkommende operasjoner i filen hvert X sekund eller hver Y operasjon.
- RDB og AOF er en kombinasjon av de to foregÄende.
Alle metoder har sine fordeler og ulemper, jeg vil ikke liste opp alle, men bare rette oppmerksomheten mot det jeg anser som ikke-Äpenbare punkter.
For Ä lagre et RDB-snapshot mÄ du fÞrst kalle FORK. Hvis det er mye data, kan dette henge hele Redis i en periode pÄ flere millisekunder til et sekund. I tillegg mÄ systemet allokere minne til et slikt snapshot, noe som fÞrer til behovet for Ä ha en dobbel reserve av RAM pÄ den logiske maskinen: hvis 8 GB er allokert til Redis, bÞr 16 vÊre tilgjengelig pÄ den virtuelle maskinen som fÞlger med.
For det andre er det problemer med delvis synkronisering. I AOF-modus, nÄr man kobler til en slave pÄ nytt, kan full synkronisering utfÞres i stedet for delvis. Jeg klarte ikke Ä finne ut hvorfor dette skjer. Men det er verdt Ä huske pÄ.
Disse to punktene fÄr oss allerede til Ä tenke pÄ om vi virkelig trenger disse dataene pÄ disken, hvis alt uansett dupliseres av slaver. Data kan bare gÄ tapt hvis alle slaver svikter, og dette er et problem pÄ nivÄet "brann i DC". Som et kompromiss kan vi foreslÄ Ä lagre data bare pÄ slaver, men i dette tilfellet mÄ vi sÞrge for at disse slavene aldri blir mastere under nÞdgjenoppretting (for dette er det en slaveprioritetsinnstilling i konfigurasjonen deres). For oss selv tenker vi i hvert spesifikke tilfelle pÄ om det er nÞdvendig Ä lagre data pÄ disk, og oftest er svaret "nei".
Konklusjon
Avslutningsvis hÄper jeg at jeg har klart Ä gi en generell idé om hvordan redis-cluster fungerer til de som aldri har hÞrt om det, og ogsÄ rettet oppmerksomheten mot noen ikke-Äpenbare punkter for de som har brukt det lenge.
Takk for tiden din, og som alltid er alle kommentarer om dette emnet velkomne.
Kilde: www.habr.com
