En side som svarer på 200 ms mot en lokal Redis, bruker fire sekunder når klienten sitter bak en VPN, mens tellerne på serveren står stille. Den trege loggen viser ingenting over en millisekund, CPU-grafen er flat, og instansen betjener andre klienter uten klager. Det som er endret, er avstanden, og det som multipliserer avstanden, er antall ganger koden din stopper og venter. Gå forespørselens vei fra klienten og utover, og løsningen er nesten alltid færre sekvensielle ventetider i stedet for en raskere server.

Start ved klienten, ikke ved serverens målinger

Følg klientprosessen mellom den første og den siste kommandoen. Hvis sporet viser et svar, en pause og deretter neste kommando, betaler du en full rundtur per kommando, og ingen mengde servertuning endrer det. Den trege loggen er feil instrument her, fordi den registrerer kjøretid og bevisst utelukker kommunikasjons-I/O. En ren treg logg ved siden av et tregt endepunkt er signaturen på et rundturproblem.

Mål selve veien før du rører koden. redis-cli -h redis.example.internal --latency sender gjentatte PING-er og skriver ut gjennomsnittlig forespørsels- og svartid, som er din kostnad per utveksling. Gang det med antall sekvensielle kommandoer i én brukerhandling, og du har en nedre grense for endepunktet.

Tell rundturene som én brukerhandling faktisk trenger

Ta ett enkelt endepunkt og skriv ned hvert Redis-kall i rekkefølge, også de som er skjult i en ORM, en sesjons-middleware eller et funksjonsflagg-oppslag. De fleste trege endepunkter viser seg å gjøre tjue eller tretti kall der tre ville vært nok, og de skjulte er vanligvis flertallet.

En avhengighetskjede kan ikke slås sammen: hvis den andre kommandoen trenger nøkkelen den første returnerer, er ventetiden reell, og de eneste alternativene er en annen datamodell eller en serveroperasjon som uttrykker hele trinnet på én gang. Uavhengige lesinger er en annen sak, fordi ingenting tvinger deg til å vente på det første svaret før du sender det andre. Merk hvert kall som avhengig eller uavhengig før du endrer noe, og formen på løsningen blir åpenbar.

Tallet som betyr noe, er sekvensielle ventetider, ikke totale kommandoer. Tretti kommandoer i én batch koster fortsatt én ventetid.

Batch bare kommandoene som ikke avhenger av hverandre

En pipeline setter uavhengige kommandoer i kø og samler svarene i rekkefølge, og gjør N ventetider til én. De fleste klienter tilbyr det som en blokk, en callback eller en kontekstbehandler i stedet for en egen tilkoblingsmodus, så sjekk API-et versjonen din leverer. Gevinsten skalerer med rundturtiden, og det er nettopp derfor det betyr noe på en VPN og knapt merkes på localhost.

import redis

r = redis.Redis(host="redis.example.internal", port=6379, socket_timeout=2)
pipe = r.pipeline(transaction=False)
for key in ("user:1001", "user:1002", "user:1003"):
    pipe.get(key)
print(pipe.execute())

Send transaction=False når du bare vil batche. Som standard pakker klienten batchen inn i MULTI og EXEC, noe som gjør den atomisk og endrer hva andre klienter kan observere underveis. Atomisitet er en beslutning om korrekthet, ikke en ytelsesknapp, og en pipeline er ikke en transaksjon bare fordi begge reduserer rundturer.

Les hvert svar i stedet for bare batchinnsendingen. En kommando i kø kan returnere en feil mens batchen som helhet fullføres, og en klient som kaster svarlisten, gjør en mislykket skriving til en stille. Sammenlign lengden på svarlisten med antall kommandoer du satte i kø.

Hold tilkoblingen i live mellom handlinger

Hver ny tilkobling betaler for navneoppslag, en TCP-håndtrykk, en TLS-håndtrykk og en AUTH, og over en VPN er hver av dem en rundtur du ikke kan batche bort. Opprett klienten én gang per prosess og gjenbruk den, eller bruk poolen biblioteket ditt tilbyr med begrenset størrelse. Gjenoppkobling per forespørsel er den nest vanligste årsaken til dette symptomet etter ventetider per kommando.

Hold det private vertsnavnet i konfigurasjonen i stedet for en bokstavelig adresse. Sertifikatvalidering og tjenesteidentitet gjelder fortsatt på et privat nettverk, og fastlåsing av en IP bryter sammen i det øyeblikket leverandøren omnummererer et subnett. Hvis oppslaget er den trege delen, reparer resolverstien i stedet for tilkoblingsstrengen.

Sett en eksplisitt socket-timeout slik at en fastlåst tunnel feiler raskt i stedet for å henge en arbeider. Bekreft deretter at poolen virkelig gjenbrukes ved å logge tilkoblingsoppretting i klienten.

Dimensjoner batchen før den blir et minneproblem

Redis holder køede svar i hele batchens varighet, og klienten holder deretter det parsede resultatet. En pipeline med ti tusen store verdier bytter nettverksventetider mot minnetopper og lange pauser i begge ender.

Velg batchstørrelse etter svarmengde i stedet for kommandotall. Noen hundre små kommandoer i én batch er vanligvis behagelig, mens hundre nyttelaster på flere kilobyte ikke er det. Del på bytes så vel som på antall, og hold hver batch innenfor latensbudsjettet endepunktet faktisk har.

Mål ende-til-ende etter endringen: redis-cli -h redis.example.internal --latency-history viser om veien selv er stabil, og din egen forespørselstimer viser om endepunktet ble bedre. Hvis endepunktet fortsatt er tregt mens latenshistorikken er flat, er den gjenværende kostnaden serverarbeid eller din egen serialisering, og neste steg er en profil av handleren i stedet for nok en batch-endring.

Relaterte artikler