Redis prek VPN je počasen: zmanjšajte število krogov na zahtevo
VPN oddaljenega klica Redis ne spremeni v lokalnega. Načrtujte število krogov na zahtevo, znova uporabljajte povezave in pipeline držite stran od transakcij.
Stran, ki z lokalnim Redisom odgovori v 200 ms, potrebuje štiri sekunde, ko klient sedi za VPN, medtem ko števci strežnika mirujejo. Slow Log ne pokaže ničesar nad milisekundo, graf CPU je raven in instanca streže druge kliente brez pritožb. Kar se je spremenilo, je razdalja, in tisto, kar razdaljo pomnoži, je število krat, ko se vaša koda ustavi in čaka. Pojdite po poti zahteve od klienta navzven in popravek je skoraj vedno manj zaporednih čakanj, ne hitrejši strežnik.
Začnite pri klientu, ne pri metrikah strežnika
Opazujte proces klienta med prvim in zadnjim ukazom. Če sled pokaže odgovor, premor in nato naslednji ukaz, plačujete cel krog na ukaz in nobeno nastavljanje strežnika tega ne bo spremenilo. Slow Log je tu napačen pripomoček, ker beleži čas izvajanja in komunikacijski I/O namerno izključuje. Čist Slow Log ob počasnem endpointu je podpis težave s številom krogov.
Najprej izmerite samo pot, šele nato posegajte v kodo. redis-cli -h redis.example.internal --latency pošilja ponavljajoče se PINGe in izpiše povprečni čas zahteve in odgovora, kar je vaš strošek na eno izmenjavo. Pomnožite ga s številom zaporednih ukazov v eni uporabniški akciji in dobite spodnjo mejo za endpoint.
Preštejte, koliko krogov ena uporabniška akcija zares potrebuje
Vzemite en endpoint in po vrsti zapišite vsak klic Redisa, vključno s tistimi, ki se skrivajo v ORM, v session middleware ali v iskanju feature flaga. Večina počasnih endpointov naredi dvajset ali trideset klicev tam, kjer bi zadostovali trije, skriti pa so običajno večina.
Verige odvisnosti ni mogoče stisniti: če drugi ukaz potrebuje ključ, ki ga je vrnil prvi, je čakanje resnično in edini možnosti sta drugačen podatkovni model ali strežniška operacija, ki cel korak izrazi naenkrat. Neodvisna branja so drug primer, ker vas nič ne sili čakati na prvi odgovor, preden pošljete drugega. Vsak klic označite kot odvisen ali neodvisen, preden karkoli uredite, in oblika popravka postane očitna.
Pomembno je število zaporednih čakanj, ne skupno število ukazov. Trideset ukazov v enem paketu še vedno stane eno čakanje.
Združujte v pakete samo ukaze, ki niso odvisni drug od drugega
Pipeline postavi neodvisne ukaze v čakalno vrsto in odgovore pobere po vrsti, s čimer N čakanj spremeni v eno. Večina klientov jo izpostavi kot blok, callback ali kontekstni upravitelj, ne kot ločen način povezave, zato preverite API, ki ga ponuja nameščena različica. Dobiček raste s časom kroga, zato je pomemben na VPN in se na localhostu komaj pozna.
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())
Posredujte transaction=False takrat, ko želite samo paketno združevanje. Pri privzeti nastavitvi klient paket ovije v MULTI in EXEC, kar ga naredi atomarnega in spremeni, kaj drugi klienti vidijo med poletom. Atomarnost je odločitev o pravilnosti, ne gumb za zmogljivost, in pipeline ni transakcija samo zato, ker oba zmanjšujeta število krogov.
Preberite vsak odgovor, ne le oddajo paketa. Ukaz v čakalni vrsti lahko vrne napako, medtem ko se paket kot celota zaključi, in klient, ki seznam odgovorov zavrže, spremeni neuspeli zapis v tihi. Primerjajte dolžino seznama odgovorov s številom ukazov, ki ste jih dali v vrsto.
Ohranjajte povezavo živo med akcijami
Vsaka nova povezava plača razreševanje imena, rokovanje TCP, rokovanje TLS in AUTH, prek VPN pa je vsako od tega krog, ki ga ne morete združiti v paket. Ustvarite klienta enkrat na proces in ga uporabljajte znova, ali uporabite pool, ki ga ponuja vaša knjižnica, z omejeno velikostjo. Ponovno povezovanje na vsako zahtevo je drugi najpogostejši vzrok te simptomatike takoj za čakanjem na vsak ukaz.
Zasebno ime gostitelja hranite v konfiguraciji, ne kot dobesedni naslov. Preverjanje certifikata in identiteta storitve veljata tudi v zasebnem omrežju, pripenjanje IP pa se zlomi v trenutku, ko ponudnik preštevilči podmrežo. Če je počasno razreševanje, popravite pot do resolverja, ne niza povezave.
Nastavite izrecen socket timeout, da zataknjen tunel hitro odpove, namesto da obesi delavca. Nato z beleženjem ustvarjanja povezav v klientu potrdite, da se pool res znova uporablja.
Velikost paketa določite, preden postane težava s pomnilnikom
Redis drži odgovore v čakalni vrsti ves čas paketa, klient pa nato drži razčlenjeni rezultat. Pipeline z deset tisoč velikimi vrednostmi zamenja čakanje na omrežje za skoke pomnilnika in dolge premore na obeh koncih.
Velikost paketa izberite glede na obseg odgovorov, ne glede na število ukazov. Nekaj sto majhnih ukazov v enem paketu je običajno udobno, sto večkilobajtnih payloadov pa ne. Delite po bajtih in po številu ter vsak paket držite znotraj latence, ki jo endpoint dejansko ima.
Po spremembi merite od začetka do konca: redis-cli -h redis.example.internal --latency-history pokaže, ali je pot sama stabilna, vaš lastni merilnik zahtev pa pokaže, ali se je endpoint izboljšal. Če je endpoint še vedno počasen, medtem ko je zgodovina latence ravna, je preostali strošek delo na strežniku ali vaša serializacija, naslednji korak pa je profil obdelovalca, ne nova sprememba paketnega združevanja.