
NÀr man arbetar med en produkt som har utvecklats i mer Àn ett decennium Àr det inte förvÄnande att man stöter pÄ förÄldrad teknik. Men vad hÀnder om ni om sex mÄnader mÄste hantera en belastning som Àr tio gÄnger högre, och kostnaden för driftstopp ökar hundra gÄnger? I sÄ fall behöver ni en duktig Highload Engineer. Men i avsaknad av en sÄdan, fick jag ta pÄ mig ansvaret för att lösa problemet. I den första delen av artikeln kommer jag att berÀtta om vÄr övergÄng frÄn Redis till Redis-cluster, och i den andra delen kommer jag att ge tips om hur man börjar anvÀnda klustret och vad man ska tÀnka pÄ vid drift.
Val av teknik
Ăr det sĂ„ dĂ„ligt separat Redis (standalone redis) med en konfiguration av 1 master och N slavar? Varför kallar jag det för förĂ„ldrad teknik?
Nej, Redis Àr inte sÄ dÄligt... Men det finns vissa brister som inte kan ignoreras.
För det första stödjer inte Redis mekanismer för katastrofÄterstÀllning efter att master har fallit. För att lösa detta problem anvÀnde vi en konfiguration med automatisk omdirigering av VIP till den nya mastern, förÀndring av rollen av en av slavarna och omkoppling av de andra. Denna mekanism fungerade, men man kan inte kalla den ett pÄlitligt lösning. För det första skedde falska larm, och för det andra var den engÄngslösning, och efter utlöst incident krÀvdes manuella ÄtgÀrder för att ÄterstÀlla systemet.
För det andra orsakade det att det bara fanns en master problem med sharding. Man var tvungen att skapa flera oberoende kluster "1 master och N slavar", sedan manuellt fördela databaserna över dessa maskiner och hoppas att ingen databas nÀsta dag skulle vÀxa sÄ mycket att den mÄste flyttas till en separat instans.
Vilka alternativ finns?
- Det dyraste och mest omfattande alternativet Àr Redis-Enterprise. Detta Àr en fÀrdig lösning med full teknisk support. Trots att det verkar perfekt ur tekniskt perspektiv passade det oss inte av ideologiska skÀl.
- Redis-cluster. Det finns inbyggt stöd för katastrofÄterkoppling av master och sharding. GrÀnssnittet skiljer sig nÀstan inte frÄn den vanliga versionen. Det ser lovande ut, vi kommer att diskutera fallgroparna senare.
- Tarantool, Memcache, Aerospike och andra. Alla dessa verktyg gör ungefÀr samma sak. Men var och en har sina brister. Vi har valt att inte lÀgga alla Àgg i en korg. Memcache och Tarantool anvÀnder vi för andra uppgifter, och för att förutse, har vi haft fler problem med dem i vÄr praktik.
AnvÀndningsspecifika
LÄt oss titta pÄ vilka uppgifter vi historiskt har löst med Redis och vilken funktionalitet vi har anvÀnt:
- Cache inför förfrÄgningar till externa tjÀnster som 2GIS | Golang
GET SET MGET MSET "VĂLJ DB"
- Cache inför MYSQL | PHP
GET SET MGET MSET SCAN "NYCKEL EFTER MĂNSTER" "VĂLJ DB"
- Huvudlagring för tjÀnsten som arbetar med sessioner och koordinatorer för förare | Golang
GET SET MGET MSET "VĂLJ DB" "LĂGG TILL GEO NYCKEL" "HĂMTA GEO NYCKEL" SCAN
Som ni ser, ingen avancerad matematik. Vad Àr dÄ svÄrigheten? LÄt oss gÄ igenom varje metod separat.
Metod
Beskrivning
Egenskaper för Redis-kluster
Lösning
GET SET
Skriva/lÀsa en nyckel
MGET MSET
Skriva/lÀsa flera nycklar
Nycklarna kommer att ligga pÄ olika noder. FÀrdiga bibliotek kan göra multi-operationer endast inom en nods grÀnser.
ErsÀtt MGET med pipeline av N GET operationer
VĂLJ DB
VĂ€lja databasen som vi ska arbeta med
Stöder inte flera databaser
LĂ€gg allt i en databas. LĂ€gg till prefix till nycklarna.
SCAN
GĂ„ igenom alla nycklar i databasen
Eftersom vi har en databas, Àr det för kostsamt att gÄ igenom alla nycklar i klustret.
UpprÀtthÄlla invariant inom en nyckel och göra HSCAN pÄ denna nyckel. Eller helt avstÄ.
GEO
Operationer med geo-nyckeln
Geo-nyckeln kan inte shardas
NYCKEL EFTER MĂNSTER
Söka efter nyckel efter mönster
Eftersom vi har en databas, kommer vi att söka bland alla nycklar i klustret. För kostsamt.
AvstÄ eller upprÀtthÄlla invariant, som i fallet med SCAN.
Redis vs Redis-kluster
Vad förlorar vi och vad fÄr vi genom att gÄ över till kluster?
- Nackdelar: vi förlorar funktionaliteten hos flera databaser.
- Om vi vill lagra logiskt orelaterade data i ett kluster, mÄste vi göra lösningar i form av prefix.
- Vi förlorar alla operationer «per databas», som SCAN, DBSIZE, CLEAR DB, etc.
- Multi-operationer har blivit betydligt svÄrare att genomföra, eftersom det kan krÀvas att man kontaktar flera noder.
- Fördelar:
- Hög tillgÀnglighet i form av nödfunktionering av master.
- Sharding pÄ Redis-sidan.
- Ăverföring av data mellan noder atomĂ€rt och utan driftstopp.
- Tillfoga och omfördela resurser och belastningar utan driftstopp.
Jag skulle dra slutsatsen att om du inte behöver sÀkerstÀlla en hög nivÄ av driftsÀkerhet sÄ Àr det inte vÀrt att flytta till ett kluster, eftersom det kan vara en icke-trivial uppgift. Men om man frÄn början vÀljer mellan en separat version och ett kluster, sÄ bör man vÀlja kluster, eftersom det inte Àr sÀmre och dessutom avlastar en del av huvudvÀrken.
Förberedelse för flytt
LÄt oss börja med kraven för flytten:
- Den bör vara sömlös. En total stopp av servicen i 5 minuter Àr oacceptabelt för oss.
- Den bör vara sÄ sÀker och gradvis som möjligt. Vi vill ha viss kontroll över situationen. Att bara köra allt pÄ en gÄng och be en bön till ÄterstÀllningsknappen Àr inte nÄgot vi önskar.
- Minimala datarförluster vid flytt. Vi förstÄr att det blir mycket svÄrt att flytta atomÀrt, sÄ vi accepterar viss desynkronisering mellan data i vanlig och kluster Redis.
UnderhÄll av klustret
Innan sjÀlva flytten bör vi tÀnka pÄ om vi kan underhÄlla klustret:
- Diagram. Vi anvÀnder Prometheus och Grafana för att visa belastningen pÄ processorer, anvÀnda minne, antal kunder, antal operationer GET, SET, AUTH, etc.
- Expertis. FörestĂ€ll dig att det stora klustret kommer att vara ditt ansvar i morgon. Om det gĂ„r sönder kan ingen, förutom du, laga det. Om det börjar lagga kommer alla att komma till dig. Om resurser mĂ„ste lĂ€ggas till eller belastningen omfördelas â Ă„terigen till dig. För att inte bli grĂ„hĂ„rig vid 25 bör man förutse dessa scenarier och testa i förvĂ€g hur teknologin kommer att bete sig vid olika Ă„tgĂ€rder. Vi kommer att prata mer om detta i avsnittet "Expertis".
- Ăvervakning och notifieringar. NĂ€r klustret gĂ„r sönder vill man veta det först. HĂ€r har vi nöjt oss med att notifiera att alla noder returnerar samma information om klustrets tillstĂ„nd (ja, det kan vara annorlunda). Andra problem mĂ€rks snabbare genom notifieringar frĂ„n Redis-klienttjĂ€nster.
Flytt
Hur vi ska flytta:
- Först mĂ„ste vi förbereda biblioteket för att arbeta med klustret. Som grund för GĐŸ-versionen anvĂ€nde vi go-redis och gjorde nĂ„gra justeringar. Vi implementerade Multi-metoder genom pipelines och justerade Ă€ven reglerna för begĂ€rningsĂ„terupprepning. Med PHP-versionen stötte vi pĂ„ fler problem, men i slutĂ€ndan valde vi php-redis. Nyligen introducerade de klusterstöd, vilket vi anser ser bra ut.
- DÀrefter mÄste vi distribuera sjÀlva klustret. Detta görs bokstavligen med tvÄ kommandon baserat pÄ konfigurationsfilen. Vi kommer att diskutera instÀllningen mer nedan.
- För en gradvis övergÄng anvÀnder vi dry-mode. Eftersom vi har tvÄ versioner av biblioteket med identiskt grÀnssnitt (en för den vanliga versionen och en för klustret), Àr det enkelt att skapa en wrapper som arbetar med den separata versionen och samtidigt duplicera alla begÀrningar till klustret, jÀmföra svaren och logga avvikelserna (i vÄrt fall i NewRelic). PÄ sÄ sÀtt, Àven om kluster-versionen skulle gÄ sönder vid utrullningen, pÄverkas vÄr produktion inte.
- Genom att rulla ut klustret i dry-lÀge kan vi lugnt titta pÄ diagrammet över svarens avvikelser. Om andelen fel lÄngsamt men sÀkert rör sig mot nÄgon liten konstant, dÄ Àr allt bra. Varför finns det avvikelser ÀndÄ? För att inlÀsning i den separata versionen sker nÄgot tidigare Àn i klustret, och pÄ grund av mikrolag kan data skilja sig Ät. Det ÄterstÄr bara att kolla loggarna över avvikelserna, och om de alla Àr förklarliga genom icke-atomÀr inlÀsning, kan vi gÄ vidare.
- Nu kan vi vÀxla dry-mode tillbaka. Vi kommer att lÀsa och skriva frÄn klustret, och duplicera i den separata versionen. Varför? Under den kommande veckan vill vi observera klustrets arbete. Om det visar sig att det finns problem vid hög belastning, eller om vi missade nÄgot, har vi alltid en nödkoppling till den gamla koden och aktuella data tack vare dry-mode.
- Det ÄterstÄr att stÀnga av dry-mode och demontera den separata versionen.
Expertis
Först en kort översikt av klusterets uppbyggnad.
Först och frÀmst Àr Redis en key-value-lagring. Valfria strÀngar anvÀnds som nycklar. VÀrdena kan vara nummer, strÀngar och hela datastrukturer. Det finns mÄnga av de senare, men för att förstÄ den allmÀnna uppbyggnaden Àr detta inte viktigt.
Den nÀsta abstraheringsnivÄn efter nycklarna Àr slots (SLOTS). Varje nyckel tillhör en av 16 383 slots. Inom varje slot kan det finnas hur mÄnga nycklar som helst. SÄledes delas alla nycklar in i 16 383 icke-överlappande mÀngder.

Vidare mÄste det finnas N master-noder i klustret. Varje nod kan representeras som en separat Redis-instans som vet allt om de andra noderna inom klustret. Varje master-nod innehÄller ett visst antal slots. Varje slot tillhör endast en master-nod. Alla slots mÄste fördelas mellan noderna. Om nÄgra slots inte fördelas, kommer nycklarna som lagras i dem att vara otillgÀngliga. Det Àr meningsfullt att köra varje master-nod pÄ en separat logisk eller fysisk maskin. Det Àr ocksÄ vÀrt att komma ihÄg att varje nod arbetar endast pÄ en kÀrna, och om du vill köra flera instanser av Redis pÄ en logisk maskin, se till att de körs pÄ olika kÀrnor (vi har inte provat detta, men i teorin ska allt fungera). I grund och botten sÀkerstÀller master-noder vanlig sharding, och fler master-noder gör det möjligt att skala skriv- och lÀsfrÄgor.
Efter att alla nycklar har fördelats över slots och slots har spridits över master-noder, kan ett godtyckligt antal slave-noder lÀggas till varje master-nod. Inom varje sÄdan "master-slave"-koppling kommer normal replikering att ske. Slavar behövs för att skala lÀsförfrÄgningar och för failover i hÀndelse av att master-noden gÄr ner.

Nu ska vi prata om operationer som vi bör kunna utföra.
Vi kommer att interagera med systemet via Redis-CLI. Eftersom Redis inte har en enda ingÄngspunkt kan följande operationer utföras pÄ vilken nod som helst. I varje punkt pÄpekar jag sÀrskilt möjligheten att utföra operationen under belastning.
- Det första och viktigaste vi behöver Àr operationen cluster nodes. Den returnerar status för klustret, visar listan över noder, deras roller, fördelning av slots etc. Ytterligare information kan erhÄllas med cluster info och cluster slots.
- Det vore bra att kunna lÀgga till och ta bort noder. För detta finns operationerna cluster meet och cluster forget. Observera att cluster forget mÄste tillÀmpas pÄ VARJE nod, bÄde pÄ master- och replika-noder. Cluster meet behöver dÀremot endast anropas pÄ en nod. Denna skillnad kan vara förvirrande, sÄ det Àr bÀst att lÀra sig om den innan man sÀtter klustret i drift. Att lÀgga till en nod görs sÀkert under drift och pÄverkar inte klustrets funktion (vilket Àr logiskt). Om du planerar att ta bort en nod frÄn klustret, se till att det inte finns nÄgra slots kvar (annars riskerar du att förlora Ätkomsten till alla nycklar pÄ den noden). Ta heller inte bort en master som har slavar, eftersom det annars kommer utföras onödig röstning för en ny master. Om det redan inte finns nÄgra slots pÄ noderna Àr det ett litet problem, men varför ha onödiga val nÀr man först kan ta bort slavarna.
- Om det Àr nödvÀndigt att tvÄngsmÀssigt byta plats pÄ master och slav, dÄ Àr kommandot cluster failover lÀmpligt. NÀr du anropar det under drift, mÄste man förstÄ att under operationens utförande kommer mastern att vara otillgÀnglig. Vanligtvis sker bytet pÄ mindre Àn en sekund, men det Àr inte atomÀrt. Du kan rÀkna med att vissa förfrÄgningar till mastern kommer att sluta med fel under den tiden.
- Innan du tar bort en nod frÄn klustret fÄr det inte finnas nÄgra slots kvar pÄ den. Det Àr bÀttre att omfördela dem med hjÀlp av kommandot cluster reshard. Slots kommer att flyttas frÄn en master till en annan. Hela operationen kan ta flera minuter, beroende pÄ mÀngden data som flyttas, men överföringsprocessen Àr sÀker och pÄverkar inte klustrets funktion. PÄ sÄ sÀtt kan alla data flyttas frÄn en nod till en annan under belastning utan att oroa sig för deras tillgÀnglighet. Men det finns vissa nyanser. För det första Àr datatransfer kopplad till viss belastning pÄ bÄde mottagnings- och avsÀndarnoden. Om mottagningsnoden redan Àr kraftigt belastad pÄ processorn, bör du inte belasta den med nya data ocksÄ. För det andra, sÄ snart det inte finns nÄgra slots kvar pÄ avsÀndarmastern, kommer alla dess slavar omedelbart att övergÄ till den master dit dessa slots har flyttats. Problemet Àr att alla dessa slavar samtidigt kommer att vilja synkronisera data. Och du fÄr tur om detta blir delvis, snarare Àn fullstÀndig synkronisering. TÀnk pÄ detta och kombinera operationerna för att flytta slots och stÀnga/överföra slavar. Eller hoppas att du har tillrÀckligt med marginal.
- Vad ska man göra om du vid överföringen upptÀcker att du förlorat nÄgra slots? Jag hoppas att detta problem inte drabbar dig, men om det skulle hÀnda finns operationen cluster fix. Den kommer mer eller mindre att slumpmÀssigt fördela slots mellan noderna. Jag rekommenderar att du kontrollerar dess funktion efter att ha tagit bort en nod med fördelade slots frÄn klustret. Eftersom data i de odistribuerade slots redan Àr otillgÀngliga Àr det för sent att oroa sig för tillgÀngligheten av dessa slots. Samtidigt kommer operationen inte att pÄverka de distribuerade slots.
- En annan anvÀndbar operation Àr monitor. Den lÄter dig se en lista över alla förfrÄgningar som görs till noden i realtid. Dessutom kan du göra en grep pÄ den och ta reda pÄ om det finns önskad trafik.
Det Àr ocksÄ vÀrt att nÀmna proceduren för failover av master-noden. Kort sagt, den finns, och i min mening fungerar den utmÀrkt. Men man ska inte tro att om man drar ut kontakten ur vÀggen pÄ en maskin med master-nod, sÄ kommer Redis omedelbart att byta och klienterna inte kommer att mÀrka nÄgon nedtid. UtifrÄn min erfarenhet tar det nÄgra sekunder för bytet att ske. Under denna tid kommer en del data att vara otillgÀnglig: otillgÀngligheten hos master upptÀckts, noderna röstar pÄ en ny, slavar byts, data synkroniseras. Det bÀsta sÀttet att sjÀlv sÀkerstÀlla att systemet fungerar Àr att genomföra en lokal övning. SÀtt upp en kluster pÄ din laptop, ge en minimal belastning, simulera ett fall (till exempel genom att blockera portar), och bedöm bytestiden. Enligt min Äsikt, bara genom att leka med detta i ett par dagar kan man vara sÀker pÄ att teknologin fungerar. Alternativt kan man hoppas att mjukvaran som anvÀnds av hÀlften av internet sÀkert fungerar.
Konfiguration
Vanligtvis Àr konfigurationen det första som behövs för att börja arbeta med verktyget. NÀr allt fungerar vill man inte gÀrna röra konfigurationen. Det krÀvs en del anstrÀngningar för att tvinga sig sjÀlv att gÄ tillbaka till instÀllningarna och noggrant gÄ igenom dem. Enligt min minne har vi haft minst tvÄ allvarliga misstag pÄ grund av bristande uppmÀrksamhet kring konfigurationen. Var sÀrskilt uppmÀrksam pÄ följande punkter:
- timeout 0
Tiden efter vilken inaktiva anslutningar stÀngs (i sekunder). 0 - ingen stÀngs.
Inte varje bibliotek vi anvÀnder kunde stÀnga anslutningar korrekt. Genom att stÀnga av den hÀr instÀllningen riskerar vi att nÄ grÀnsen för antalet klienter. à andra sidan, om det finns ett sÄdant problem, sÄ döljer den automatiska nedkopplingen av förlorade anslutningar det, och vi kanske inte lÀgger mÀrke till det. Dessutom bör denna instÀllning inte aktiveras vid anvÀndning av persistenta anslutningar. - Save x y & appendonly yes
Spara RDB-snapshot.
Vi kommer att diskutera RDB/AOF-problemen mer ingÄende nedan. - stop-writes-on-bgsave-error no & slave-serve-stale-data yes
Om det Àr aktiverat, kommer master att sluta ta emot begÀrningar pÄ förÀndringar vid ett fel pÄ RDB-snapshotet. Om anslutningen till master förloras kan slav fortsÀtta att svara pÄ begÀrningar (yes). Eller sluta svara (no).
Vi Àr inte nöjda med att Redis förvandlas till en pumpa. - repl-ping-slave-period 5
Efter denna tidsperiod kommer vi att börja oroa oss för att mÀstaren har gÄtt sönder och att det Àr dags att genomföra en failover.
Vi mÄste manuellt hitta balansen mellan falska larm och failover. I vÄr erfarenhet Àr detta 5 sekunder. - repl-backlog-size 1024mb & epl-backlog-ttl 0
SÄ mycket data kan vi lagra i bufferten för en misslyckad replik. Om bufferten tar slut, mÄste vi synkronisera helt.
Erfarenheten visar att det Àr bÀttre att sÀtta ett högre vÀrde. Det finns mÄnga anledningar till varför en replik kan börja halka efter. Om den halkar efter, sÄ Àr det sannolikt att din mÀstare redan har svÄrt att hantera, och fullstÀndig synkronisering blir den sista droppen. - maxclients 10000
Det maximala antalet samtidiga klienter.
Enligt vÄr erfarenhet Àr det bÀttre att sÀtta ett högre vÀrde. Redis klarar sig utmÀrkt med 10 000 anslutningar. Se bara till att det finns tillrÀckligt med sockets i systemet. - maxmemory-policy volatile-ttl
Regeln för hur nycklar tas bort nÀr minnesgrÀnsen nÄs.
Det viktiga hÀr Àr inte sjÀlva regeln, utan förstÄelsen för hur detta kommer att ske. Redis kan berömmas för sin förmÄga att fungera som det ska nÀr minnesgrÀnsen nÄs.
Problem med RDB och AOF
Ăven om Redis sjĂ€lv lagrar all information i RAM, finns det Ă€ven mekanismer för att spara data pĂ„ disk. Specifikt finns det tre mekanismer:
- RDB-snapshot â en komplett avbildning av all data. StĂ€lls in med hjĂ€lp av konfigurationen SAVE X Y och lĂ€ses som "Spara en fullstĂ€ndig snapshot av all data var X sekunder, om minst Y nycklar har Ă€ndrats."
- Append-only file â en lista över operationer i den ordning de genomfördes. LĂ€gger till nya inkommande operationer i filen var X sekunder eller efter var Y operationer.
- RDB och AOF â en kombination av de tvĂ„ tidigare.
Alla metoder har sina fördelar och nackdelar, jag kommer inte att lista dem alla, utan endast pÄpeka de som, enligt mig, inte Àr sÄ uppenbara.
För det första, att spara en RDB-snapshot krÀver att FORK anropas. Om det finns mycket data kan detta frysa hela Redis under en period frÄn nÄgra millisekunder till en sekund. Dessutom behöver systemet reservera minne för en sÄdan snapshot, vilket leder till behovet av att hÄlla ett dubbelt lager av RAM pÄ den logiska maskinen: om 8 GB tilldelas Redis, mÄste det finnas 16 GB tillgÀngligt pÄ virtuella maskinen.
För det andra finns det problem med partiell synkronisering. I AOF-lÀge kan en fullstÀndig synkronisering ske istÀllet för partiell vid Äteranslutning av slaven. Jag kunde inte förstÄ varför detta hÀnder, men det Àr vÀrt att komma ihÄg.
Dessa tvÄ punkter fÄr en att fundera pÄ om vi verkligen behöver dessa data pÄ disk, om de redan dupliceras av slavarna. Data kan endast gÄ förlorade om alla slavar gÄr sönder, vilket Àr ett problem pÄ nivÄ "brand i datacentret". Som en kompromiss kan man föreslÄ att endast spara data pÄ slavarna, men i sÄ fall mÄste man sÀkerstÀlla att dessa slavar aldrig blir master vid en katastrofÄterstÀllning (för detta finns det instÀllningar för slavarnas prioritet i deras konfiguration). Vi övervÀger i varje enskilt fall om det Àr nödvÀndigt att spara data pÄ disk, och oftast svarar vi "nej".
Slutsats
Som avslutning hoppas jag att jag har kunnat ge en allmÀn översikt av hur redis-cluster fungerar till de som aldrig har hört talas om det, och att jag Àven har uppmÀrksammat vissa oklara punkter för de som har anvÀnt det lÀnge.
Tack för er tid, och som vanligt Àr kommentarer i Àmnet alltid vÀlkomna.
KĂ€lla: habr.com
