
NÄr man jobber med et produkt som har utviklet seg i over ti Är, er det ikke overraskende Ä finne utdaterte teknologier i det. Men hva skjer hvis du om seks mÄneder mÄ hÄndtere en belastning som er ti ganger hÞyere, og kostnaden ved nedetid Þker hundre ganger? I sÄ fall trenger du en dyktig Highload Engineer. Men siden vi ikke hadde en slik tilgjengelig, ble problemet overlatt til meg. I del én av artikkelen vil jeg fortelle om overgangen fra Redis til Redis-cluster, og i del to vil jeg gi rÄd om hvordan man begynner Ä bruke clusteren og hva man bÞr vÊre oppmerksom pÄ under driften.
Valg av teknologi
Er det sÄ ille med en egen Redis (standalone redis) i en konfigurasjon med 1 master og N slaver? Hvorfor kaller jeg det en utdatert teknologi?
Nei, Redis er ikke sÄ ille... Men det er noen ulemper som ikke kan ignoreres.
For det fÞrste stÞtter ikke Redis mekanismer for gjenoppretting etter feil pÄ masteren. For Ä lÞse dette problemet brukte vi en konfigurasjon med automatisk overfÞring av VIP-er til den nye masteren, endring av rollen til en av slavene og bytting av de andre. Denne mekanismen fungerte, men man kunne ikke kalle det en pÄlitelig lÞsning. For det fÞrste oppsto det falske positive varsler, og for det andre var det engangsbruk, og etter en utlÞsing var det behov for manuell hÄndtering for Ä fÄ det tilbake til normal.
For det andre fÞrte det Ä ha bare én master til problemer med sharding. Man mÄtte opprette flere uavhengige klynger med '1 master og N slaver', deretter manuelt fordele databasene pÄ disse maskinene og hÄpe at en av databasene ikke ble sÄ stor at den mÄtte flyttes til en egen instans.
Hva er alternativene?
- Den dyreste og mest omfattende lĂžsningen er Redis-Enterprise. Dette er en pakkelĂžsning med full teknisk stĂžtte. Selv om det ser perfekt ut fra et teknisk synspunkt, passet det ikke for oss av ideologiske grunner.
- Redis-cluster. Ut av boksen har det stĂžtte for automatisk failover av masteren og sharding. Grensesnittet er nesten identisk med den vanlige versjonen. Det ser lovende ut, og vi vil diskutere mulige fallgruver senere.
- Tarantool, Memcache, Aerospike og andre. Alle disse verktÞyene gjÞr omtrent det samme. Men hver av dem har sine egne ulemper. Vi har bestemt oss for ikke Ä legge alle eggene i en kurv. Memcache og Tarantool bruker vi til andre oppgaver, og for Ä vÊre fÞr vi kommer til poenget, skal jeg si at vi har hatt flere problemer med dem i vÄr praksis.
Spesifikasjonen for bruk
La oss se pÄ hvilke oppgaver vi historisk har lÞst med Redis og hvilken funksjonalitet vi har brukt:
- Cache fĂžr forespĂžrselen til eksterne tjenester som 2GIS | Golang
GET SET MGET MSET "SELECT DB"
- Cache fĂžr MYSQL | PHP
GET SET MGET MSET SCAN "KEY BY PATTERN" "SELECT DB"
- Hovedlagring for tjenesten som arbeider med Þkter og koordinater til sjÄfÞrer | Golang
GET SET MGET MSET "SELECT DB" "ADD GEO KEY" "GET GEO KEY" SCAN
Som du ser, ingen hÞyere matematikk. Hva er sÄ kompleksiteten? La oss se nÊrmere pÄ hver metode.
Metode
Description
Egenskaper ved Redis-kluster
Solution
GET SET
Skrive/lese nĂžkkel
MGET MSET
Skrive/lese flere nĂžkler
NÞklene vil ligge pÄ forskjellige noder. Ferdige biblioteker kan kun gjÞre Multi-operasjoner innenfor en node.
Erstatt MGET med en pipeline av N GET-operasjoner
SELECT DB
Velge databasen vi skal bruke
StĂžtter ikke flere databaser
Oppbevar alt i én database. Legg til prefikser til nÞklene
SCAN
GĂ„ gjennom alle nĂžklene i databasen
Siden vi har én database, er det for kostbart Ä gÄ gjennom alle nÞklene i klusteret.
Opprettholde invariant innenfor en nÞkkel og gjÞre HSCAN pÄ denne nÞkkelen. Eller avstÄ helt.
GEO
Operasjoner med geonĂžkkel
GeonĂžkkelen deles ikke opp.
KEY BY PATTERN
SÞke etter nÞkkel basert pÄ mÞnster
Siden vi har én database, skal vi sÞke gjennom alle nÞklene i klusteret. For kostbart.
AvstÄ eller opprettholde invariant, som i tilfellet med SCAN.
Redis vs Redis-kluster
Hva mister vi og hva fÄr vi ved Ä gÄ over til kluster?
- Ulemper: vi mister funksjonaliteten til flere databaser.
- Hvis vi vil lagre logisk usammenhengende data i ett kluster, mÄ vi lage lÞsninger med prefikser.
- Vi mister alle operasjoner "per database", som SCAN, DBSIZE, CLEAR DB osv.
- Multi-operasjoner har blitt betydelig vanskeligere Ă„ implementere, fordi det kan kreve tilgang til flere noder.
- Fordeler:
- Feiltoleranse i form av nĂždskifting av hovedserver.
- Shardingside pÄ Redis.
- OverfĂžring av data mellom noder atomisk og uten nedetid.
- Legge til og omfordele kapasitet og belastninger uten nedetid.
Jeg vil konkludere med at si at hvis du ikke trenger Ä sikre et hÞyt nivÄ av tilgjengelighet, sÄ er det ikke verdt Ä flytte til en klynge, da dette kan vÊre en krevende oppgave. Men hvis man fÞrst velger mellom en separat versjon og en klynge, bÞr man velge klyngen, da den ikke er dÄrligere, og i tillegg vil den ta bort noe av bekymringen.
Forberedelse til flytting
Vi begynner med kravene til flyttingen:
- Den mÄ vÊre sÞmlÞs. En total stopp av tjenesten i 5 minutter er uakseptabelt for oss.
- Den bÞr vÊre sÄ sikker og gradvis som mulig. Vi Þnsker Ä ha kontroll over situasjonen. à kaste alt pÄ en gang og stole pÄ nedgraderingsknappen er ikke noe vi Þnsker.
- Minimale datatap under flyttingen. Vi forstÄr at det vil vÊre svÊrt vanskelig Ä flytte atomÊrt, sÄ vi aksepterer en viss desynkronisering mellom dataene i vanlig og klynge Redis.
Vedlikehold av klyngen
FĂžr selve flyttingen, bĂžr vi vurdere om vi kan vedlikeholde klyngen:
- Grafikk. Vi bruker Prometheus og Grafana for grafikk over CPU-bruk, minnebruk, antall klienter, antall GET, SET, AUTH-operasjoner, osv.
- Ekspertise. Tenk deg at i morgen vil du ha ansvaret for en enorm klynge. Hvis den krasjer, sÄ er det ingen andre enn deg som kan fikse den. Hvis den begynner Ä fungere sakte - vil alle komme til deg. Hvis ressurser mÄ legges til eller belastning mÄ omfordeles - igjen til deg. For Ä unngÄ Ä bli grÄhÄret i en alder av 25, bÞr man forutse disse situasjonene og teste pÄ forhÄnd hvordan teknologien vil oppfÞre seg under ulike handlinger. Vi vil diskutere dette nÊrmere i delen om 'Ekspertise'.
- OvervÄkning og varsler. NÄr klyngen krasjer, Þnsker vi Ä bli informert fÞrst. Her har vi begrenset oss til varsler om at alle noder returnerer den samme informasjonen om klyngens tilstand (ja, det kan vÊre annerledes). Andre problemer blir raskere oppdaget gjennom varsler fra Redis-klienttjenester.
Flytting
Hvordan vi skal flytte:
- FÞrst mÄ vi forberede biblioteket for Ä arbeide med klyngen. Som grunnlag for versjonen i Go har vi tatt go-redis og tilpasset det litt. Vi implementerte Multi-metoder gjennom pipelines og justerte reglene for gjentakelse av forespÞrslene. Med PHP-versjonen oppsto det flere problemer, men til slutt har vi landet pÄ php-redis. Nylig har de introdusert stÞtte for klynger, og etter vÄrt syn ser det bra ut.
- Deretter mÄ vi sette opp selve klyngen. Dette gjÞres bokstavelig talt med to kommandoer basert pÄ konfigurasjonsfilen. Vi vil diskutere innstillingene mer detaljert nedenfor.
- For en gradvis overgang bruker vi dry-mode. Siden vi har to versjoner av biblioteket med identisk grensesnitt (en for vanlig versjon og en for klynge), er det enkelt Ä lage en wrapper som jobber med den separate versjonen og samtidig dupliserer alle forespÞrslene til klyngen, sammenligner svarene og skriver avvikene i loggene (i vÄrt tilfelle i NewRelic). Dermed, selv om klyngeversjonen bryter ved utrullingen, vil produksjonen vÄr ikke bli berÞrt.
- NÄr vi lanserer klyngen i dry-modus, kan vi rolig se pÄ diagrammet over avvik i svarene. Hvis andelen feil sakte men sikkert beveger seg mot en liten konstant, betyr det at alt er i orden. Hvorfor er det fortsatt avvik? Fordi opptak i den separate versjonen skjer litt tidligere enn i klyngen, og pÄ grunn av mikrologgene kan dataene avvike. Det gjenstÄr bare Ä se pÄ avviksloggene, og hvis alle er forklarlige med hensyn til ikke-atomaritet i opptakene, kan vi gÄ videre.
- NÄ kan vi skifte dry-mode tilbake. Vi vil skrive og lese fra klyngen, samtidig som vi dupliserer til den separate versjonen. Hvorfor? I lÞpet av den neste uken Þnsker vi Ä observere hvordan klyngen fungerer. Hvis det viser seg at det er problemer under hÞy belastning, eller vi har oversett noe, har vi alltid en nÞdprosess for Ä gÄ tilbake til gammel kode og aktuelle data takket vÊre dry-mode.
- Det gjenstÄr bare Ä deaktivere dry-mode og demontere den separate versjonen.
Ekspertise
FĂžrst en kort oversikt over hvordan klyngen er strukturert.
FÞrst og fremst er Redis et key-value lagringssystem. VilkÄrlige strenger brukes som nÞkler. Verdiene kan vÊre tall, strenger og komplekse strukturer. Det finnes et stort antall av de siste, men for Ä forstÄ den generelle strukturen er dette ikke viktig.
Det neste nivÄet av abstraksjon etter nÞklene er slottene (SLOTS). Hver nÞkkel tilhÞrer en av 16 383 slots. Inne i hver slot kan det vÊre sÄ mange nÞkler som Þnskes. Dermed deles alle nÞkler opp i 16 383 ikke-overlappende mengder.

Videre mÄ det vÊre N master-noder i klyngen. Hver node kan betraktes som en separat Redis-instans som vet alt om de andre nodene inne i klyngen. Hver master-node inneholder et visst antall slots. Hver slot tilhÞrer bare én master-node. Alle slots mÄ fordeles mellom nodene. Hvis noen slots ikke er fordelt, vil nÞklene som lagres i dem vÊre utilgjengelige. Hver master-node gir mening Ä kjÞre pÄ en separat logisk eller fysisk maskin. Det er ogsÄ viktig Ä huske at hver node kun kjÞrer pÄ én kjerne, og hvis du Þnsker Ä kjÞre flere Redis-instanserer pÄ en logisk maskin, mÄ du sÞrge for at de kjÞrer pÄ forskjellige kjerner (vi har ikke prÞvd dette, men i teorien skal det fungere). I hovedsak gir master-nodene vanlig sharding, og flere master-noder gjÞr det mulig Ä skalere bÄde skrive- og leseforespÞrslene.
Etter at alle nÞkler er fordelt pÄ slots, og slots er fordelt pÄ master-nodene, kan det legges til et vilkÄrlig antall slave-noder til hver master-node. Inne i hver «master-slave» kobling vil vanlig replikering fungere. Slaver er nÞdvendige for Ä skalere leseforespÞrslene og for failover i tilfelle masteren svikter.

La oss nÄ snakke om operasjonene vi helst bÞr kunne utfÞre.
Vi vil kontakte systemet via Redis-CLI. Siden Redis ikke har et enkelt tilgangspunkt, kan de fÞlgende operasjonene utfÞres pÄ hvilken som helst av nodene. Jeg vil spesifisere hver enkelt operasjon med tanke pÄ muligheten for Ä utfÞre den under belastning.
- Det fÞrste og viktigste vi trenger: operasjonen cluster nodes. Den returnerer tilstanden til klyngen, viser listen over noder, deres roller, fordelingen av slots osv. Ytterligere informasjon kan fÄs ved hjelp av cluster info og cluster slots.
- Det ville vÊre bra Ä kunne legge til og fjerne noder. For dette finnes operasjonene cluster meet og cluster forget. VÊr oppmerksom pÄ at cluster forget mÄ brukes pÄ HVER node, bÄde pÄ mastere og replikaer. Og cluster meet trenger kun kalles pÄ én node. Denne forskjellen kan vÊre forvirrende, sÄ det er best Ä bli klar over den fÞr man setter klusteret i drift. à legge til en node gjÞres trygt i drift og pÄvirker ikke arbeidet til klusteret (noe som er logisk). Hvis du imidlertid planlegger Ä fjerne en node fra klusteret, bÞr du forsikre deg om at det ikke er noen slots igjen (ellers risikerer du Ä miste tilgang til alle nÞklene pÄ denne noden). Fjern heller ikke masteren hvis den har slaver, ellers vil det bli unÞdvendig avstemning for en ny master. Hvis det ikke er noen slots igjen pÄ nodene, er det et lite problem, men hvorfor velge det unÞdvendige, hvis man kan fjerne slavene fÞrst.
- Hvis du mÄ tvinge bytte mellom master og slave, kan kommandoen cluster failover brukes. NÄr du kaller denne i drift, mÄ du forstÄ at masteren vil vÊre utilgjengelig under operasjonen. Vanligvis skjer byttet pÄ mindre enn et sekund, men det er ikke atomisk. Du kan forvente at deler av forespÞrslene til masteren vil feile i lÞpet av denne tiden.
- FÞr du fjerner en node fra klyngen, bÞr det ikke vÊre noen slots igjen pÄ den. Det er best Ä omfordele dem med kommandoen cluster reshard. Slots vil bli overfÞrt fra en master til en annen. Hele operasjonen kan ta flere minutter, avhengig av mengden data som overfÞres, men prosessen er trygg og pÄvirker ikke driften av klyngen. Dermed kan alle data overfÞres fra en node til en annen selv under belastning, uten Ä bekymre seg for tilgjengeligheten. Imidlertid er det visse nyanser. For det fÞrste er dataoverfÞring forbundet med en viss belastning pÄ bÄde mottaker- og avsender-noden. Hvis mottakeren allerede er sterkt belastet pÄ prosessoren, bÞr du ikke belaste den med mottak av nye data. For det andre, sÄ snart det ikke er noen slots igjen pÄ master-avsenderen, vil alle dens slaves umiddelbart gÄ over til den masteren hvor disse slotsene ble flyttet. Problemet er at alle disse slave-nodene vil Þnske Ä synkronisere dataene samtidig. Og du er heldig hvis dette er delvis, og ikke full synkronisering. Ta hensyn til dette, og kombiner operasjoner med flytting av slots med Ä frakoble/flytte slaves. Eller hÄp at du har tilstrekkelig kapasitet.
- Hva gjÞr du hvis du oppdager at du har mistet slots under overfÞringen? Jeg hÄper dette problemet ikke vil berÞre deg, men hvis det skjer, finnes det en operasjon kalt cluster fix. Den vil tilfeldigvis fordele slotsene pÄ nodene. Jeg anbefaler Ä sjekke hvordan den fungerer ved Ä fjerne en node med fordelte slots fra klyngen fÞrst. Siden data i ufordelte slots allerede er utilgjengelige, er det for sent Ä bekymre seg for tilgangen til disse slotsene. PÄ sin side vil operasjonen ikke pÄvirke de fordelte slotsene.
- En annen nyttig operasjon er monitor. Den lar deg se hele listen over forespÞrslene som kommer til noden i sanntid. Dessuten kan du bruke grep pÄ den for Ä finne ut om det er Þnsket trafikk.
Det er ogsÄ viktig Ä nevne prosedyren for nÞdovergang til master. Kort sagt er det en prosedyre, og etter min mening fungerer den utmerket. Men man skal ikke tro at hvis man trekker ut stikkontakten fra maskinen med master-noden, vil Redis umiddelbart overta og kundene ikke vil merke noen avbrudd. Etter min erfaring tar det flere sekunder fÞr overgangen skjer. I lÞpet av denne tiden vil deler av dataene vÊre utilgjengelige: masterens utilgjengelighet oppdages, nodene stemmer over ny, slaver byttes over, og data synkroniseres. Den beste mÄten Ä sikre seg om at systemet fungerer, er Ä gjennomfÞre lokale Þvelser. Sett opp en klynge pÄ din bÊrbare PC, gi minimal last, simuler et nedbrudd (for eksempel ved Ä blokkere porter), og evaluer overgangen. Etter min mening kan man fÞrst vÊre sikker pÄ teknologiens funksjonalitet etter Ä ha lekt med det i en dag eller to. Eller hÄpe pÄ at programvaren som brukes av halve internett, fungerer som den skal.
Konfigurasjon
Som regel er konfigurasjonen det fÞrste man trenger for Ä begynne Ä bruke verktÞyet. Og nÄr alt er oppe og gÄr, Þnsker man ikke Ä rÞre konfigurasjonen. Det kreves spesifikke anstrengelser for Ä tvinge seg selv tilbake til innstillingene og gÄ dem grundig igjennom. Etter min erfaring har vi hatt minst to alvorlige feil pÄ grunn av uoppmerksomhet mot konfigurasjonen. VÊr spesielt oppmerksom pÄ fÞlgende punkter:
- timeout 0
Tiden det tar fĂžr inaktive forbindelser lukkes (i sekunder). 0 â lukkes ikke
Ikke alle vÄre biblioteker var i stand til Ä lukke forbindelser riktig. Ved Ä deaktivere denne innstillingen risikerer vi Ä nÄ grensen for antall klienter. PÄ den annen side, hvis et slikt problem eksisterer, vil automatisk brudd av tapte forbindelser maskere det, og vi kan gÄ glipp av det. Videre bÞr man ikke aktivere denne innstillingen nÄr man bruker persist-forbindelser. - Save x y & appendonly yes
Lagring av RDB-snapshot.
Problemer knyttet til RDB/AOF vil vi diskutere i detalj nedenfor. - stop-writes-on-bgsave-error no & slave-serve-stale-data yes
Hvis aktivert, vil master slutte Ä ta imot endringsforespÞrsel ved et RDB-snapshot-feil. Hvis forbindelsen til master er tapt, kan slaven fortsette Ä svare pÄ forespÞrsel (yes). Eller slutte Ä svare (no)
Vi er ikke komfortable med situasjonen der Redis blir til en gresskar. - repl-ping-slave-period 5
I lĂžpet av denne tidsperioden vil vi begynne Ă„ bekymre oss for at masteren er brutt sammen og at vi bĂžr utfĂžre en failover-prosedyre.
Vi mÄ manuelt finne balansen mellom falske alarmer og utlÞsing av failover. I vÄr erfaring tar dette 5 sekunder. - repl-backlog-size 1024mb & epl-backlog-ttl 0
Slik mengde data kan vi lagre i bufferet for en avvikende replika. Hvis bufferet fylles opp, mÄ vi synkronisere helt.
Erfaringen tilsier at det er bedre Ä sette verdien litt hÞyere. Det finnes flere grunner til at en replika kan begynne Ä henge etter. Hvis den henger etter, er det sannsynlig at masteren din allerede sliter, og full synkronisering vil bli drÄpen som fÄr begeret til Ä renne over. - maxclients 10000
Det maksimale antallet samtidige klienter.
IfÞlge vÄr erfaring er det bedre Ä sette verdien hÞyere. Redis klarer seg fint med 10 000 tilkoblinger. Bare sÞrg for at systemet har nok sokler. - maxmemory-policy volatile-ttl
Reglene for hvordan nÞkler blir fjernet nÄr grensen for tilgjengelig minne nÄs.
Her er det viktigere ikke selve regelen, men forstÄelsen av hvordan dette vil skje. Redis kan roses for dets evne til Ä fungere godt nÄr minnegrensen nÄs.
Problemer med RDB og AOF
Selv om Redis lagrer all informasjon i RAM, finnes det ogsÄ mekanismer for Ä lagre data pÄ disk. NÊrmere bestemt finnes det tre mekanismer:
- RDB-snapshot â et fullt snapshot av all data. Settes opp med konfigurasjonen SAVE X Y og leses som "Lagre et fullstendig snapshot av alle data hvert X sekunder, hvis minst Y nĂžkler har blitt endret."
- Append-only file â en liste over operasjoner i rekkefĂžlge etter utfĂžrelse. Legger til nye ankomne operasjoner til filen hvert X sekunder eller hver Y operasjoner.
- RDB og AOF â en kombinasjon av de to forrige.
Alle metodene har sine fordeler og ulemper, jeg vil ikke liste dem alle, men vil bare pÄpeke det som, etter min mening, ikke er sÄ Äpenbare punkter.
For det fÞrste, for Ä lagre en RDB-snapshot kreves det Ä kalle FORK. Hvis det er mye data, kan dette hengslet hele Redis i en periode fra noen millisekunder til ett 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 tildelt Redis, mÄ det vÊre tilgjengelig 16 GB pÄ den virtuelle maskinen.
For det andre er det problemer med delvis synkronisering. I AOF-modus kan det, ved gjenoppretting av slave, utfÞres en fullstendig synkronisering i stedet for delvis. Hvorfor dette skjer, klarte jeg ikke Ä forstÄ. Men det er verdt Ä huske pÄ.
Disse to punktene fÄr oss allerede til Ä tenke pÄ om vi virkelig trenger disse dataene pÄ disk, nÄr de allerede er duplisert av slavene. Data kan bare gÄ tapt dersom alle slavene svikter, og det er et problem av "brann i datasenteret"-nivÄ. Som et kompromiss kan man foreslÄ Ä lagre data kun pÄ slavene, men i sÄ fall mÄ man sÞrge for at disse slavene aldri blir master ved nÞdgjenoppretting (det finnes en innstilling for prioritering av slaver i deres konfigurasjon). I hvert enkelt tilfelle vurderer vi om vi skal lagre data pÄ disk, og vi svarer oftest "nei".
Konklusjon
Avslutningsvis hÄper jeg jeg har gitt en generell oversikt over hvordan redis-cluster fungerer til de som aldri har hÞrt om det, og ogsÄ pÄpekt noen ikke-Äpenbare punkter for de som allerede har brukt det en stund.
Takk for tiden din, og som alltid er kommentarer om emnet velkomne.
Kilde: habr.com
