Om å flytte fra Redis til Redis-cluster

Om å flytte fra Redis til Redis-cluster

Når det kommer til et produkt som har utviklet seg i mer enn et tiår, er det ikke overraskende å finne utdaterte teknologier i det. Men hva om du om seks måneder må holde belastningen 10 ganger høyere, og kostnadene ved fall vil øke hundrevis av ganger? I dette tilfellet trenger du en kul Highload Engineer. Men i mangel av en hushjelp betrodde de meg å løse problemet. I den første delen av artikkelen vil jeg fortelle deg hvordan vi gikk fra Redis til Redis-cluster, og i den andre delen vil jeg gi råd om hvordan du kan begynne å bruke klyngen og hva du bør være oppmerksom på når du bruker den.

Teknologivalg

Er det så ille? separat Redis (frittstående redis) i en konfigurasjon med 1 master og N slaver? Hvorfor kaller jeg det foreldet teknologi?

Nei, Redis er ikke så ille... Det er imidlertid noen mangler som ikke kan ignoreres.

  • For det første støtter ikke Redis gjenopprettingsmekanismer etter en masterfeil. For å løse dette problemet brukte vi en konfigurasjon med automatisk overføring av VIP-er til en ny master, endret rollen til en av slavene og byttet resten. Denne mekanismen fungerte, men den kunne ikke kalles en pålitelig løsning. For det første oppstod det falske alarmer, og for det andre var det engangs, og etter drift var det nødvendig med manuelle handlinger for å lade fjæren.

  • For det andre førte det å ha bare en mester til problemet med skjæring. Vi måtte opprette flere uavhengige klynger «1 master og N slaver», og deretter distribuere databasene manuelt blant disse maskinene og håpe at i morgen ikke ville en av databasene svelle så mye at den måtte flyttes til en egen instans.

Hva er alternativene?

  • Den dyreste og rikeste løsningen er Redis-Enterprise. Dette er en boksløsning med full teknisk støtte. Til tross for at det ser ideelt ut fra et teknisk synspunkt, passet det ikke oss av ideologiske grunner.
  • Redis-klynge. Ut av esken er det støtte for master failover og sharding. Grensesnittet er nesten ikke forskjellig fra den vanlige versjonen. Det ser lovende ut, vi snakker om fallgruvene senere.
  • Tarantool, Memcache, Aerospike og andre. Alle disse verktøyene gjør stort sett det samme. Men hver har sine egne mangler. Vi bestemte oss for å ikke legge alle eggene våre i én kurv. Vi bruker Memcache og Tarantool til andre oppgaver, og når vi 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 problemer vi historisk har løst med Redis og hvilken funksjonalitet vi brukte:

  • Buffer før forespørsler til eksterne tjenester som 2GIS | Golang

    GET SET MGET MSET "VELG DB"

  • Buffer før MYSQL | PHP

    GET SET MGET MSET SCAN "KEY BY PATTERN" "SELECT DB"

  • Hovedlageret for tjenesten for arbeid med økter og sjåførkoordinater | Golang

    GET SET MGET MSET "SELECT DB" "ADD GEO KEY" "GET GEO KEY" SCAN

Som du kan se, ingen høyere matematikk. Hva er så vanskeligheten? La oss se på hver metode separat.

metode
beskrivelse
Funksjoner av Redis-cluster
beslutning

KLAR
Skrive/lese nøkkel

MGET MSET
Skriv/les flere nøkler
Nøklene vil være på forskjellige noder. Ferdige biblioteker kan utføre multioperasjoner bare innenfor én node
Erstatt MGET med en pipeline av N GET-operasjoner

VELG DB
Velg basen vi skal jobbe med
Støtter ikke flere databaser
Legg 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
Oppretthold en invariant innenfor én nøkkel og gjør en HSCAN på denne nøkkelen. Eller nekte helt

GEO
Operasjoner med en geonøkkel
Geotøkkelen er ikke sønderdelt

NØKKEL ETTER MØNSTER
Søker etter en nøkkel etter mønster
Siden vi har én database, vil vi søke på tvers av alle nøklene i klyngen. For dyrt
Avslå eller opprettholde 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 "base" operasjoner, som SCAN, DBSIZE, CLEAR DB, etc.
    • Multioperasjoner har blitt mye vanskeligere å implementere fordi det kan kreve tilgang til flere noder.
  • fordeler:
    • Feiltoleranse i form av master failover.
    • Sharding på Redis-siden.
    • Overfør data mellom noder atomært og uten nedetid.
    • Legg til og omfordel kapasitet og laster uten nedetid.

Jeg vil konkludere med at hvis du ikke trenger å gi et høyt nivå av feiltoleranse, så er det ikke verdt det å flytte til en klynge, fordi det kan være en ikke-triviell oppgave. Men hvis du i utgangspunktet velger mellom en separat versjon og en klyngeversjon, bør du velge en klynge, siden det ikke er verre og i tillegg vil lindre noe av hodepinen.

Forbereder seg på å flytte

La oss starte med kravene til flytting:

  • Det skal være sømløst. En fullstendig stopp av tjenesten i 5 minutter passer ikke oss.
  • Det skal være så trygt og gradvis som mulig. Jeg vil ha litt kontroll over situasjonen. Vi ønsker ikke å dumpe alt på en gang og be over rollback-knappen.
  • Minimalt tap av data ved flytting. Vi forstår at det vil være svært vanskelig å flytte atomært, så vi tillater litt desynkronisering mellom data i vanlige og grupperte Redis.

Klyngevedlikehold

Rett før flyttingen bør vi tenke på om vi kan støtte klyngen:

  • Diagrammer. Vi bruker Prometheus og Grafana til å grafere CPU-belastning, minnebruk, antall klienter, antall GET-, SET-, AUTH-operasjoner, etc.
  • Ekspertise. Tenk deg at i morgen vil du ha en enorm klynge under ditt ansvar. Hvis det går i stykker, kan ingen andre enn du fikse det. Hvis han begynner å bremse, vil alle løpe mot deg. Hvis du trenger å legge til ressurser eller omfordele lasten, kom tilbake til deg. For ikke å bli grå ved 25, er det tilrådelig å sørge for disse tilfellene og sjekke på forhånd hvordan teknologien vil oppføre seg under visse handlinger. La oss snakke om dette mer detaljert i "Kompetanse" -delen.
  • Overvåking og varsler. Når en klynge bryter sammen, vil du være den første som får vite om den. Her begrenset vi oss til et varsel om at alle noder returnerer samme informasjon om tilstanden til klyngen (ja, det skjer annerledes). Og andre problemer kan oppdages raskere av varsler fra Redis-klienttjenester.

kryssing

Slik skal vi flytte:

  • Først av alt må du forberede et bibliotek for å jobbe med klyngen. Vi tok go-redis som grunnlag for Go-versjonen og endret den litt for å passe oss selv. Vi implementerte Multi-metoder gjennom pipelines, og korrigerte også litt reglene for gjentatte forespørsler. PHP-versjonen hadde flere problemer, men vi slo oss til slutt på php-redis. De introduserte nylig klyngestøtte, og det ser bra ut etter vår mening.
  • Deretter må du distribuere selve klyngen. Dette gjøres bokstavelig talt i to kommandoer basert på konfigurasjonsfilen. Vi vil diskutere innstillingen mer detaljert nedenfor.
  • For gradvis bevegelse bruker vi tørrmodus. Siden vi har to versjoner av biblioteket med samme grensesnitt (en for den vanlige versjonen, den andre for klyngen), koster det ingenting å lage en wrapper som vil fungere med en separat versjon og parallelt duplisere alle forespørsler til klyngen, sammenligne svar og skriv avvik i loggene (i vårt tilfelle i NewRelic). Selv om klyngeversjonen går i stykker 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 feilraten sakte men sikkert beveger seg mot en eller annen liten konstant, så er alt bra. Hvorfor er det fortsatt avvik? Fordi opptak i en egen versjon skjer litt tidligere enn i klyngen, og på grunn av mikrolag, kan dataene divergere. Alt som gjenstår er å se på avviksloggene, og hvis de alle er forklart av postens ikke-atomisitet, kan vi gå videre.
  • Nå kan du bytte tørr-modus i motsatt retning. Vi vil skrive og lese fra klyngen, og duplisere den til en egen versjon. For hva? I løpet av neste uke vil jeg gjerne observere klyngens arbeid. Hvis det plutselig viser seg at det er problemer ved topplast, eller vi ikke tok hensyn til noe, har vi alltid en nødrulling til den gamle koden og gjeldende data takket være tørrmodus.
  • Alt som gjenstår er å deaktivere tørrmodus og demontere den separate versjonen.

Ekspertise

Først kort om klyngedesignet.

Først av alt er Redis en nøkkelverdibutikk. Vilkårlige strenger brukes som nøkler. Tall, strenger og hele strukturer kan brukes som verdier. Det er veldig mange av de siste, men for å forstå den generelle strukturen er dette ikke viktig for oss.
Det neste abstraksjonsnivået etter nøkler er spor (SLOTS). Hver nøkkel tilhører en av 16 383 spor. Det kan være et hvilket som helst antall nøkler inne i hvert spor. Dermed er alle nøkler delt inn i 16 383 usammenhengende sett.
Om å flytte fra Redis til Redis-cluster

Deretter må det være N hovednoder i klyngen. Hver node kan betraktes som en separat Redis-instans som vet alt om andre noder i klyngen. Hver masternode inneholder et antall spor. Hvert spor tilhører kun én hovednode. Alle spor må fordeles mellom noder. Hvis noen spor ikke er tildelt, 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-forekomster på samme logiske maskin, sørg for at de kjører på forskjellige kjerner (vi har ikke prøvd dette, men i teorien burde det fungere) . I hovedsak gir masternoder regelmessig sharding, og flere masternoder lar skrive- og leseforespørsler skaleres.

Etter at alle nøklene er fordelt mellom sporene, og sporene er spredt blant masternodene, kan et vilkårlig antall slavenoder legges til hver masternode. Innenfor hver slik master-slave-kobling vil normal replikering fungere. Slaver er nødvendig for å skalere leseforespørsler og for failover i tilfelle masterfeil.
Om å flytte fra Redis til Redis-cluster

La oss nå snakke om operasjoner som det ville være bedre å kunne gjøre.

Vi vil få tilgang til systemet via Redis-CLI. Siden Redis ikke har et enkelt inngangspunkt, kan du utføre følgende operasjoner på hvilken som helst av nodene. På hvert punkt trekker jeg separat oppmerksomhet til muligheten for å utføre operasjonen under belastning.

  • Det første og viktigste vi trenger er cluster node-operasjonen. Den returnerer klyngens tilstand, viser en liste over noder, deres roller, sporfordeling, etc. Mer informasjon kan fås ved å bruke klyngeinfo og klyngespor.
  • Det ville vært fint å kunne legge til og fjerne noder. For dette formålet er det cluster meet og cluster forget operasjoner. Vær oppmerksom på at cluster forget må brukes på HVER node, både master og replikaer. Og cluster meet trenger bare å bli kalt på én node. Denne forskjellen kan være foruroligende, så det er best å lære om det før du går live med klyngen din. Å legge til en node gjøres trygt i kamp og påvirker ikke driften av klyngen på noen måte (noe som er logisk). Hvis du skal fjerne en node fra klyngen, bør du sørge for at det ikke er spor igjen på den (ellers risikerer du å miste tilgangen til alle nøklene på denne noden). Slett heller ikke en master som har slaver, ellers vil det bli utført en unødvendig avstemning på en ny master. Hvis nodene ikke lenger har spor, så er dette et lite problem, men hvorfor trenger vi ekstra valg hvis vi kan slette slavene først.
  • Hvis du trenger å bytte master- og slaveposisjoner med kraft, vil klyngefailover-kommandoen gjøre det. Når du kaller det i kamp, ​​må du forstå at mesteren ikke vil være tilgjengelig under operasjonen. Vanligvis skjer bryteren på mindre enn et sekund, men er ikke atomær. Du kan forvente at noen forespørsler til masteren vil mislykkes i løpet av denne tiden.
  • Før du fjerner en node fra klyngen, skal det ikke være spor igjen på den. Det er bedre å omfordele dem ved å bruke kommandoen cluster reshard. Spor vil bli overført fra en master til en annen. Hele operasjonen kan ta flere minutter, det avhenger av datavolumet 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 uten å bekymre deg for tilgjengeligheten. Imidlertid er det også finesser. For det første er dataoverføring forbundet med en viss belastning på mottaker- og avsendernoden. Hvis mottakernoden allerede er tungt belastet på prosessoren, bør du ikke laste den med mottak av nye data. For det andre, så snart det ikke er et eneste spor igjen på den senderende masteren, vil alle dens slaver umiddelbart gå til masteren som disse sporene ble overført til. Og problemet er at alle disse slavene vil ønske å synkronisere data på en gang. Og du vil være heldig hvis det er delvis i stedet for fullstendig synkronisering. Ta hensyn til dette og kombiner operasjonene med å overføre spor og deaktivere/overføre slaver. Eller håper at du har tilstrekkelig sikkerhetsmargin.
  • Hva bør du gjøre hvis du under overføringen finner ut at du har mistet spilleautomatene dine et sted? Jeg håper dette problemet ikke påvirker deg, men hvis det gjør det, er det en klyngefiksoperasjon. I det minste vil hun spre sporene over nodene i en tilfeldig rekkefølge. Jeg anbefaler å sjekke funksjonen ved først å fjerne noden med distribuerte spor fra klyngen. Siden data i ikke-allokerte spor allerede er utilgjengelige, er det for sent å bekymre seg for problemer med tilgjengeligheten til disse sporene. I sin tur vil operasjonen ikke påvirke distribuerte spor.
  • En annen nyttig operasjon er monitor. Den lar deg se i sanntid hele listen over forespørsler som går til noden. Dessuten kan du grep den og finne ut om det er nødvendig trafikk.

Det er også verdt å nevne master failover-prosedyren. Kort sagt, det eksisterer, og etter min mening fungerer det utmerket. Men ikke tro at hvis du kobler fra strømledningen på en maskin med en masternode, vil Redis umiddelbart bytte over og klienter vil ikke merke tapet. I min praksis skjer vekslingen på noen få sekunder. I løpet av denne tiden vil noen av dataene være utilgjengelige: masterens utilgjengelighet oppdages, noder stemmer på en ny, slaver byttes, data synkroniseres. Den beste måten å forsikre seg om at ordningen fungerer på er å gjennomføre lokale øvelser. Hev klyngen på den bærbare datamaskinen, gi den en minimumsbelastning, simuler et krasj (for eksempel ved å blokkere portene), og evaluer byttehastigheten. Etter min mening, bare etter å ha spilt på denne måten i en dag eller to kan du være trygg på driften av teknologien. Vel, eller håper at programvaren som halvparten av Internett bruker sannsynligvis fungerer.

Konfigurasjon

Ofte er konfigurasjonen det første du trenger for å begynne å jobbe med verktøyet. Og når alt fungerer, vil du ikke engang berøre konfigurasjonen. Det krever litt innsats å tvinge deg selv til å gå tilbake til innstillingene og gå nøye gjennom dem. I mitt minne hadde vi minst to alvorlige feil på grunn av uoppmerksomhet på konfigurasjonen. Vær spesielt oppmerksom på følgende punkter:

  • timeout 0
    Tiden som inaktive tilkoblinger lukkes etter (i sekunder). 0 - ikke lukk
    Ikke alle bibliotekene våre var i stand til å lukke tilkoblinger på riktig måte. Ved å deaktivere denne innstillingen risikerer vi å nå grensen for antall klienter. På den annen side, hvis det er et slikt problem, vil automatisk avslutning av tapte tilkoblinger maskere det, og vi vil kanskje ikke merke det. I tillegg bør du ikke aktivere denne innstillingen når du bruker vedvarende tilkoblinger.
  • Lagre xy & appendonly ja
    Lagrer et RDB-øyeblikksbilde.
    Vi vil diskutere RDB/AOF-spørsmål i detalj nedenfor.
  • stop-writes-on-bgsave-error no & slave-serve-stale-data ja
    Hvis aktivert, hvis RDB-øyeblikksbildet bryter, vil masteren slutte å godta endringsforespørsler. Hvis forbindelsen til masteren mister, kan slaven fortsette å svare på forespørsler (ja). Eller slutter å svare (nei)
    Vi er ikke fornøyd med situasjonen der Redis blir til et gresskar.
  • repl-ping-slave-periode 5
    Etter denne tidsperioden vil vi begynne å bekymre oss for at masteren har brutt sammen, og det er på tide å utføre failover-prosedyren.
    Du må manuelt finne en balanse mellom falske positiver og utløsning av en failover. I vår praksis er dette 5 sekunder.
  • repl-backlog-størrelse 1024mb og epl-backlog-ttl 0
    Vi kan lagre akkurat så mye data i en buffer for en mislykket replika. Hvis bufferen går tom, må du synkronisere fullstendig.
    Praksis tilsier at det er bedre å sette en høyere verdi. Det er mange grunner til at en kopi kan begynne å forsinke. Hvis det henger, så sliter mest sannsynlig mesteren din allerede med å takle, og full synkronisering vil være dråpen.
  • maks klienter 10000
    Maksimalt antall engangskunder.
    Vår erfaring er at det er bedre å sette en høyere verdi. Redis håndterer 10k tilkoblinger helt fint. Bare sørg for at det er nok stikkontakter på systemet.
  • maxmemory-policy volatile-ttl
    Regelen for at nøkler slettes når den tilgjengelige minnegrensen er nådd.
    Det som er viktig her er ikke selve regelen, men forståelsen av hvordan dette vil skje. Redis kan få ros for sin evne til å fungere normalt når minnegrensen er nådd.

RDB og AOF problemer

Selv om Redis selv lagrer all informasjon i RAM, er det også en mekanisme for å lagre data til disk. Mer presist, tre mekanismer:

  • RDB-snapshot - et komplett øyeblikksbilde av alle data. Still inn ved å bruke SAVE XY-konfigurasjonen og leser "Lagre et fullstendig øyeblikksbilde av alle data hvert X sekund hvis minst Y-tastene er endret."
  • Bare vedlegg fil - en liste over operasjoner i den rekkefølgen de utføres. Legger til nye innkommende operasjoner til 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 dem alle, jeg vil bare trekke oppmerksomhet til punkter som etter min mening ikke er åpenbare.

For det første krever lagring av et RDB-øyeblikksbilde å ringe FORK. Hvis det er mye data, kan dette henge hele Redis i en periode på noen millisekunder til et sekund. I tillegg må systemet tildele minne for et slikt øyeblikksbilde, noe som fører til behovet for å beholde en dobbel tilførsel av RAM på den logiske maskinen: hvis 8 GB er tildelt Redis, bør 16 GB være tilgjengelig på den virtuelle maskinen med den.

For det andre er det problemer med delvis synkronisering. I AOF-modus, når slaven er koblet til igjen, i stedet for delvis synkronisering, kan full synkronisering utføres. Hvorfor dette skjer, kunne jeg ikke forstå. Men det er verdt å huske dette.

Disse to punktene får oss allerede til å tenke på om vi virkelig trenger disse dataene på disken hvis alt allerede er duplisert av slaver. Data kan bare gå tapt hvis alle slaver svikter, og dette er et "brann i DC"-nivåproblemet. Som et kompromiss kan du foreslå å lagre data bare på slaver, men i dette tilfellet må du sørge for at disse slavene aldri vil bli en master under katastrofegjenoppretting (for dette er det en slaveprioritetsinnstilling i konfigurasjonen deres). For oss selv tenker vi i hvert enkelt tilfelle på om det er nødvendig å lagre data på disk, og som oftest er svaret "nei".

Konklusjon

Avslutningsvis håper jeg at jeg var i stand til å gi en generell ide om hvordan redis-cluster fungerer for de som ikke har hørt om det i det hele tatt, og trakk også oppmerksomhet til noen ikke-åpenbare punkter for de som har brukt det i lang tid.
Takk for at du tok deg tid, og som alltid er kommentarer om emnet velkomne.

Kilde: www.habr.com

Legg til en kommentar