
NÀr det kommer till en produkt som har utvecklats i mer Àn ett decennium Àr det inte alls förvÄnande att hitta förÄldrad teknik i den. Men vad hÀnder om du om sex mÄnader mÄste hÄlla belastningen 10 gÄnger högre, och kostnaden för fall kommer att öka hundratals gÄnger? I det hÀr fallet behöver du en cool Highload Engineer. Men i avsaknad av en piga anförtrodde de mig att lösa problemet. I den första delen av artikeln kommer jag att berÀtta hur vi gick frÄn Redis till Redis-kluster, och i den andra delen kommer jag att ge rÄd om hur du börjar anvÀnda klustret och vad du ska vara uppmÀrksam pÄ nÀr du anvÀnder det.
Teknikval
Ăr det sĂ„ illa? separata Redis (fristĂ„ende redis) i en konfiguration av 1 master och N slavar? Varför kallar jag det förĂ„ldrad teknik?
Nej, Redis Àr inte sÄ illa... Det finns dock nÄgra brister som inte gÄr att ignorera.
För det första stöder inte Redis mekanismer för ÄterstÀllning efter ett huvudfel. För att lösa detta problem anvÀnde vi en konfiguration med automatisk överföring av VIPs till en ny master, Àndrade rollen för en av slavarna och bytte resten. Denna mekanism fungerade, men den kunde inte kallas en pÄlitlig lösning. För det första uppstod falsklarm, och för det andra var det engÄngsbruk, och efter drift krÀvdes manuella ÄtgÀrder för att ladda fjÀdern.
För det andra, att bara ha en mÀstare ledde till problemet med skÀrning. Vi var tvungna att skapa flera oberoende kluster "1 master och N slavar", sedan manuellt distribuera databaserna mellan dessa maskiner och hoppas att en av databaserna i morgon inte skulle svÀlla sÄ mycket att den skulle behöva flyttas till en separat instans.
Vad Àr alternativen?
- Den dyraste och rikaste lösningen Àr Redis-Enterprise. Detta Àr en boxad lösning med full teknisk support. Trots att det ser idealiskt ut ur teknisk synvinkel passade det inte oss av ideologiska skÀl.
- Redis-kluster. Out of the box finns stöd för master failover och sharding. GrÀnssnittet skiljer sig nÀstan inte frÄn den vanliga versionen. Det ser lovande ut, vi pratar om fallgroparna senare.
- Tarantool, Memcache, Aerospike och andra. Alla dessa verktyg gör ungefÀr samma sak. Men var och en har sina egna brister. Vi bestÀmde oss för att inte lÀgga alla vÄra Àgg i en korg. Vi anvÀnder Memcache och Tarantool för andra uppgifter, och nÀr vi ser framÄt kommer jag att sÀga att det i vÄr praktik var fler problem med dem.
Specifikationer för anvÀndning
LÄt oss ta en titt pÄ vilka problem vi historiskt har löst med Redis och vilken funktionalitet vi anvÀnde:
- Cache innan förfrÄgningar till fjÀrrtjÀnster som 2GIS | Golang
GET SET MGET MSET "SELECT DB"
- Cache före MYSQL | PHP
GET SET MGET MSET SCAN "KEY BY PATTERN" "SELECT DB"
- Huvudlagringen för tjÀnsten att arbeta med sessioner och förarkoordinater | Golang
GET SET MGET MSET "SELECT DB" "ADD GEO KEY" "GET GEO KEY" SCAN
Som du kan se, ingen högre matematik. Vad Àr dÄ svÄrigheten? LÄt oss titta pÄ varje metod separat.
metod
beskrivning
Funktioner i Redis-kluster
beslutet
FĂRSTĂLL
Skriv/lÀs nyckel
MGET MSET
Skriv/lÀs flera nycklar
Nycklarna kommer att finnas pÄ olika noder. FÀrdiga bibliotek kan utföra flera operationer endast inom en nod
ErsÀtt MGET med en pipeline av N GET-operationer
VĂLJ DB
VĂ€lj den bas vi ska arbeta med
Stöder inte flera databaser
LĂ€gg allt i en databas. LĂ€gg till prefix till nycklar
SCAN
GĂ„ igenom alla nycklar i databasen
Eftersom vi har en databas Àr det för dyrt att gÄ igenom alla nycklar i klustret
BehÄll en invariant inom en nyckel och gör en HSCAN pÄ denna nyckel. Eller vÀgra helt
GEO
Operationer med en geonyckel
Geonyckeln Àr inte skÀrrad
NYCKEL EFTER MĂNSTER
Söker efter en nyckel efter mönster
Eftersom vi har en databas kommer vi att söka över alla nycklar i klustret. För dyr
Avvisa eller bibehÄll det invarianta, som i fallet med SCAN
Redis vs Redis-kluster
Vad förlorar vi och vad vinner vi nÀr vi byter till ett kluster?
- Nackdelar: vi förlorar funktionaliteten i flera databaser.
- Om vi ââvill lagra logiskt orelaterade data i ett kluster mĂ„ste vi göra kryckor i form av prefix.
- Vi förlorar alla "bas" operationer, sÄsom SCAN, DBSIZE, CLEAR DB, etc.
- Multioperationer har blivit mycket svÄrare att implementera eftersom det kan krÀva tillgÄng till flera noder.
- fördelar:
- Feltolerans i form av master failover.
- Sharding pÄ Redis-sidan.
- Ăverför data mellan noder atomĂ€rt och utan stillestĂ„nd.
- LÀgg till och omfördela kapacitet och laster utan stillestÄnd.
Jag skulle dra slutsatsen att om du inte behöver ge en hög feltolerans, sÄ Àr det inte vÀrt att flytta till ett kluster, eftersom det kan vara en icke-trivial uppgift. Men om du till en början vÀljer mellan en separat version och en klusterversion, bör du vÀlja ett kluster, eftersom det inte Àr vÀrre och dessutom kommer att lindra en del av huvudvÀrken
Förbereder för att flytta
LÄt oss börja med kraven för att flytta:
- Det ska vara sömlöst. Ett komplett servicestopp i 5 minuter passar oss inte.
- Det ska vara sÄ sÀkert och gradvis som möjligt. Jag vill ha lite kontroll över situationen. Vi vill inte dumpa allt pÄ en gÄng och be över ÄterstÀllningsknappen.
- Minimal dataförlust nÀr du flyttar. Vi förstÄr att det kommer att vara mycket svÄrt att flytta atomÀrt, sÄ vi tillÄter viss desynkronisering mellan data i vanliga och klustrade Redis.
KlusterunderhÄll
Strax innan flytten bör vi fundera pÄ om vi kan stödja klustret:
- Diagram. Vi anvÀnder Prometheus och Grafana för att plotta CPU-belastning, minnesanvÀndning, antal klienter, antal GET-, SET-, AUTH-operationer, etc.
- Expertis. FörestÀll dig att du imorgon kommer att ha ett enormt kluster under ditt ansvar. Om det gÄr sönder kan ingen annan Àn du fixa det. Om han börjar sakta ner kommer alla att springa mot dig. Om du behöver lÀgga till resurser eller omfördela belastningen, kom tillbaka till dig. För att inte bli grÄ vid 25 Àr det lÀmpligt att ta hand om dessa fall och kontrollera i förvÀg hur tekniken kommer att bete sig under vissa ÄtgÀrder. LÄt oss prata om detta mer i detalj i avsnittet "Expert".
- Ăvervakning och varningar. NĂ€r ett kluster gĂ„r sönder vill du vara den första att veta om det. HĂ€r begrĂ€nsade vi oss till ett meddelande om att alla noder returnerar samma information om klustrets tillstĂ„nd (ja, det hĂ€nder olika). Och andra problem kan upptĂ€ckas snabbare genom varningar frĂ„n Redis kundtjĂ€nst.
korsning
Hur vi ska flytta:
- Först och frÀmst mÄste du förbereda ett bibliotek för att arbeta med klustret. Vi tog go-redis som grund för Go-versionen och Àndrade den lite för att passa oss sjÀlva. Vi implementerade Multi-metoder genom pipelines och korrigerade ocksÄ en aning reglerna för att upprepa förfrÄgningar. PHP-versionen hade fler problem, men vi bestÀmde oss sÄ smÄningom pÄ php-redis. De introducerade nyligen klusterstöd och det ser bra ut enligt vÄr mening.
- DÀrefter mÄste du distribuera sjÀlva klustret. Detta görs bokstavligen i tvÄ kommandon baserat pÄ konfigurationsfilen. Vi kommer att diskutera instÀllningen mer i detalj nedan.
- För gradvis förflyttning anvÀnder vi torrlÀge. Eftersom vi har tvÄ versioner av biblioteket med samma grÀnssnitt (en för den vanliga versionen, den andra för klustret) kostar det ingenting att skapa en wrapper som fungerar med en separat version och parallellt duplicera alla förfrÄgningar till klustret, jÀmför svar och skriv avvikelser i loggarna (i vÄrt fall i NewRelic). SÄledes, Àven om klusterversionen gÄr sönder under utrullningen, kommer vÄr produktion inte att pÄverkas.
- Efter att ha rullat ut klustret i torrt lÀge kan vi lugnt titta pÄ grafen över svarsavvikelser. Om felfrekvensen sakta men sÀkert rör sig mot nÄgon liten konstant sÄ Àr allt bra. Varför finns det fortfarande avvikelser? Eftersom inspelning i en separat version sker lite tidigare Àn i klustret, och pÄ grund av mikrofördröjning, kan data divergera. Allt som ÄterstÄr Àr att titta pÄ avvikelseloggarna, och om de alla förklaras av postens icke-atomicitet, dÄ kan vi gÄ vidare.
- Nu kan du byta torrlÀge i motsatt riktning. Vi kommer att skriva och lÀsa frÄn klustret och duplicera det till en separat version. För vad? Under nÀsta vecka skulle jag vilja observera klustrets arbete. Om det plötsligt visar sig att det finns problem vid toppbelastning, eller om vi inte tagit hÀnsyn till nÄgot, har vi alltid en nödÄterstÀllning till den gamla koden och aktuella data tack vare torrlÀge.
- Allt som ÄterstÄr Àr att inaktivera torrlÀge och demontera den separata versionen.
Expertis
Först, kortfattat om klusterdesignen.
För det första Àr Redis en nyckel-vÀrde butik. Godtyckliga strÀngar anvÀnds som nycklar. Tal, strÀngar och hela strukturer kan anvÀndas som vÀrden. Det finns vÀldigt mÄnga av de senare, men för att förstÄ den allmÀnna strukturen Àr detta inte viktigt för oss.
NÀsta abstraktionsnivÄ efter nycklar Àr slots (SLOTS). Varje nyckel tillhör en av 16 383 platser. Det kan finnas hur mÄnga nycklar som helst i varje fack. SÄledes Àr alla nycklar uppdelade i 16 383 disjunkta uppsÀttningar.

DÀrefter mÄste det finnas N masternoder i klustret. Varje nod kan ses som en separat Redis-instans som vet allt om andra noder inom klustret. Varje huvudnod innehÄller ett antal luckor. Varje slot tillhör endast en huvudnod. Alla platser mÄste fördelas mellan noder. Om nÄgra platser inte tilldelas kommer nycklarna som Àr lagrade i dem att vara oÄtkomliga. Det Àr vettigt att köra varje masternod pÄ en separat logisk eller fysisk maskin. Det Àr ocksÄ vÀrt att komma ihÄg att varje nod bara körs pÄ en kÀrna, och om du vill köra flera Redis-instanser pÄ samma logiska maskin, se till att de körs pÄ olika kÀrnor (vi har inte provat detta, men i teorin borde det fungera) . I huvudsak ger masternoder regelbunden sharding, och fler masternoder tillÄter skriv- och lÀsbegÀranden att skalas.
Efter att alla nycklar Àr fördelade bland luckorna, och luckorna Àr utspridda bland masternoderna, kan ett godtyckligt antal slavnoder lÀggas till varje masternod. Inom varje sÄdan master-slavlÀnk kommer normal replikering att fungera. Slavar behövs för att skala lÀsbegÀranden och för failover i hÀndelse av masterfel.

LÄt oss nu prata om operationer som det skulle vara bÀttre att kunna göra.
Vi kommer Ät systemet via Redis-CLI. Eftersom Redis inte har en enda ingÄngspunkt kan du utföra följande operationer pÄ nÄgon av noderna. Vid varje punkt uppmÀrksammar jag separat möjligheten att utföra operationen under belastning.
- Det första och viktigaste vi behöver Àr klusternodoperationen. Den returnerar tillstÄndet för klustret, visar en lista över noder, deras roller, slotdistribution, etc. Mer information kan erhÄllas med hjÀlp av klusterinformation och klusterplatser.
- Det skulle vara trevligt att kunna lÀgga till och ta bort noder. För detta ÀndamÄl finns klustertrÀffar och klusterglömverksamheter. Observera att klusterforget mÄste tillÀmpas pÄ VARJE nod, bÄde master och repliker. Och klustermöten behöver bara anropas pÄ en nod. Denna skillnad kan vara oroande, sÄ det Àr bÀst att lÀra sig om det innan du gÄr live med ditt kluster. Att lÀgga till en nod görs sÀkert i strid och pÄverkar inte driften av klustret pÄ nÄgot sÀtt (vilket Àr logiskt). Om du ska ta bort en nod frÄn klustret bör du se till att det inte finns nÄgra luckor kvar pÄ den (annars riskerar du att förlora Ätkomst till alla nycklar pÄ denna nod). Ta inte heller bort en master som har slavar, annars kommer en onödig röst pÄ en ny master att utföras. Om noderna inte lÀngre har slots sÄ Àr detta ett litet problem, men varför behöver vi extra val om vi kan ta bort slavarna först.
- Om du mÄste byta master- och slavpositioner med kraft, kommer kommandot för kluster-failover att fungera. NÀr du kallar det i strid mÄste du förstÄ att befÀlhavaren kommer att vara otillgÀnglig under operationen. Vanligtvis sker omkopplingen pÄ mindre Àn en sekund, men Àr inte atomÀr. Du kan förvÀnta dig att vissa förfrÄgningar till mastern kommer att misslyckas under denna tid.
- Innan du tar bort en nod frÄn klustret bör det inte finnas nÄgra spÄr kvar pÄ den. Det Àr bÀttre att omfördela dem med kommandot cluster reshard. Slots kommer att överföras frÄn en master till en annan. Hela operationen kan ta flera minuter, det beror pÄ mÀngden data som överförs, men överföringsprocessen Àr sÀker och pÄverkar inte driften av klustret pÄ nÄgot sÀtt. SÄledes kan all data överföras frÄn en nod till en annan direkt under belastning och utan att behöva oroa sig för dess tillgÀnglighet. Men det finns ocksÄ finesser. För det första Àr dataöverföring förknippad med en viss belastning pÄ mottagar- och avsÀndarnoderna. Om mottagarnoden redan Àr hÄrt belastad pÄ processorn, bör du inte ladda den med att ta emot nya data. För det andra, sÄ snart det inte finns en enda lucka kvar pÄ den sÀndande mastern, kommer alla dess slavar omedelbart att gÄ till mastern till vilken dessa luckor överfördes. Och problemet Àr att alla dessa slavar kommer att vilja synkronisera data pÄ en gÄng. Och du kommer att ha tur om det Àr partiell snarare Àn fullstÀndig synkronisering. Ta hÀnsyn till detta och kombinera operationerna med att överföra slots och inaktivera/överföra slavar. Eller hoppas att du har tillrÀcklig sÀkerhetsmarginal.
- Vad ska du göra om du under överföringen upptÀcker att du har tappat bort dina slots nÄgonstans? Jag hoppas att det hÀr problemet inte pÄverkar dig, men om det gör det finns det en klusterfixoperation. à tminstone kommer hon att sprida luckorna över noderna i en slumpmÀssig ordning. Jag rekommenderar att du kontrollerar dess funktion genom att först ta bort noden med distribuerade slots frÄn klustret. Eftersom data i oallokerade platser redan Àr otillgÀngliga Àr det för sent att oroa sig för problem med tillgÀngligheten av dessa platser. à tgÀrden kommer i sin tur inte att pÄverka distribuerade slots.
- En annan anvÀndbar operation Àr monitor. Det lÄter dig se i realtid hela listan över förfrÄgningar som gÄr till noden. Dessutom kan du greppa den och ta reda pÄ om det finns den nödvÀndiga trafiken.
Det Àr ocksÄ vÀrt att nÀmna master failover-proceduren. Kort sagt, det finns, och enligt mig fungerar det utmÀrkt. Tro dock inte att om du kopplar ur nÀtsladden pÄ en maskin med en masternod kommer Redis omedelbart att byta över och kunder kommer inte att mÀrka förlusten. I min praktik sker bytet pÄ nÄgra sekunder. Under denna tid kommer en del av datan att vara otillgÀnglig: befÀlhavarens otillgÀnglighet upptÀcks, noder röstar pÄ en ny, slavar vÀxlas, data synkroniseras. Det bÀsta sÀttet att försÀkra sig om att programmet fungerar Àr att genomföra lokala övningar. Höj klustret pÄ din bÀrbara dator, ge det en minimal belastning, simulera en krasch (till exempel genom att blockera portarna) och utvÀrdera vÀxlingshastigheten. Enligt min mening, först efter att ha spelat pÄ detta sÀtt i en dag eller tvÄ kan du vara sÀker pÄ att tekniken fungerar. Tja, eller hoppas att mjukvaran som hÀlften av Internet anvÀnder förmodligen fungerar.
konfiguration
Ofta Àr konfigurationen det första du behöver för att börja arbeta med verktyget. Och nÀr allt fungerar vill du inte ens röra konfigurationen. Det tar lite anstrÀngning att tvinga dig sjÀlv att gÄ tillbaka till instÀllningarna och gÄ igenom dem noggrant. I mitt minne hade vi minst tvÄ allvarliga fel pÄ grund av ouppmÀrksamhet pÄ konfigurationen. Var sÀrskilt uppmÀrksam pÄ följande punkter:
- timeout 0
Tid efter vilken inaktiva anslutningar stÀngs (i sekunder). 0 - stÀng inte
Inte alla vÄra bibliotek kunde stÀnga anslutningar korrekt. Genom att inaktivera den hÀr instÀllningen riskerar vi att nÄ grÀnsen för antalet klienter. à andra sidan, om det finns ett sÄdant problem, kommer automatisk avslutning av förlorade anslutningar att maskera det, och vi kanske inte mÀrker det. Dessutom bör du inte aktivera den hÀr instÀllningen nÀr du anvÀnder bestÀndiga anslutningar. - Spara xy & tillÀgg ja
Sparar en RDB-ögonblicksbild.
Vi kommer att diskutera RDB/AOF-frÄgor i detalj nedan. - stop-writes-on-bgsave-error no & slave-serve-stale-data ja
Om den Àr aktiverad, om RDB-ögonblicksbilden gÄr sönder, kommer mastern att sluta acceptera ÀndringsförfrÄgningar. Om anslutningen till mastern bryts kan slaven fortsÀtta att svara pÄ förfrÄgningar (ja). Eller kommer att sluta svara (nej)
Vi Àr inte nöjda med situationen dÀr Redis förvandlas till en pumpa. - repl-ping-slave-period 5
Efter denna tidsperiod kommer vi att börja oroa oss för att mastern har gÄtt sönder och det Àr dags att utföra failover-proceduren.
Du mÄste manuellt hitta en balans mellan falska positiva resultat och att utlösa en failover. I vÄr praktik Àr detta 5 sekunder. - repl-backlog-storlek 1024mb & epl-backlog-ttl 0
Vi kan lagra exakt sÄ mycket data i en buffert för en misslyckad replik. Om bufferten tar slut mÄste du synkronisera helt.
Ăvning tyder pĂ„ 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 slĂ€pa efter. Om det slĂ€par, sĂ„ kĂ€mpar din mĂ€stare troligen redan för att klara sig, och full synkronisering kommer att vara droppen. - maxklienter 10000 XNUMX
Maximalt antal engÄngskunder.
Enligt vÄr erfarenhet Àr det bÀttre att sÀtta ett högre vÀrde. Redis hanterar 10k anslutningar bra. Se bara till att det finns tillrÀckligt med uttag pÄ systemet. - maxmemory-policy volatile-ttl
Regeln enligt vilken nycklar tas bort nÀr den tillgÀngliga 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 prisas för sin förmÄga att fungera normalt nÀr minnesgrÀnsen Àr nÄdd.
RDB och AOF problem
Ăven om Redis sjĂ€lv lagrar all information i RAM, finns det ocksĂ„ en mekanism för att spara data till disk. Mer exakt tre mekanismer:
- RDB-snapshot - en komplett ögonblicksbild av all data. StÀll in med SAVE XY-konfigurationen och lÀser "Spara en fullstÀndig ögonblicksbild av all data var X sekund om minst Y-nycklar har Àndrats."
- Enbart tillÀggsfil - en lista över operationer i den ordning de utförs. LÀgger till nya inkommande operationer till filen var X:e sekund eller varje Y-operation.
- RDB och AOF Àr en kombination av de tvÄ föregÄende.
Alla metoder har sina fördelar och nackdelar, jag kommer inte att lista dem alla, jag kommer bara att uppmÀrksamma punkter som enligt min mening inte Àr uppenbara.
För det första mÄste du anropa FORK för att spara en RDB-ögonblicksbild. Om det finns mycket data kan detta hÀnga hela Redis under en period av nÄgra millisekunder till en sekund. Dessutom behöver systemet allokera minne för en sÄdan ögonblicksbild, vilket leder till behovet av att ha en dubbel tillgÄng pÄ RAM pÄ den logiska maskinen: om 8 GB tilldelas för Redis, bör 16 GB vara tillgÀngligt pÄ den virtuella maskinen med Det.
För det andra finns det problem med partiell synkronisering. I AOF-lÀge, nÀr slaven Àr Äteransluten, istÀllet för partiell synkronisering, kan full synkronisering utföras. Varför detta hÀnder kunde jag inte förstÄ. Men det Àr vÀrt att komma ihÄg detta.
Dessa tvÄ punkter fÄr oss redan att fundera pÄ om vi verkligen behöver dessa data pÄ disken om allt redan Àr duplicerat av slavar. Data kan bara gÄ förlorade om alla slavar misslyckas, och detta Àr ett problem med "brand i DC". Som en kompromiss kan du föreslÄ att spara data endast pÄ slavar, men i det hÀr fallet mÄste du se till att dessa slavar aldrig kommer att bli en master under katastrofÄterstÀllning (för detta finns en slavprioritetsinstÀllning i deras konfiguration). För oss sjÀlva funderar vi i varje specifikt fall pÄ om det Àr nödvÀndigt att spara data pÄ disken, och oftast Àr svaret "nej".
Slutsats
Sammanfattningsvis hoppas jag att jag kunde ge en allmÀn uppfattning om hur redis-cluster fungerar för dem som inte har hört talas om det alls, och Àven uppmÀrksammat nÄgra icke-uppenbara punkter för dem som har anvÀnt det under en lÄng tid.
Tack för din tid och som alltid Àr kommentarer om Àmnet vÀlkomna.
KĂ€lla: will.com
