Redis kļūda "LOADING Redis is loading the dataset in memory" nozīmē, ka serveris darbojas, bet vēl nav pabeidzis lasīt savus datus no diska vai no galvenā servera atpakaļ RAM. Kamēr tas nav pabeigts, gandrīz katra komanda tiek noraidīta ar šo kļūdu. Nekas nav salūzis, un godīgs risinājums bieži ir pagaidīt. Darbs ir zināt, cik ilgi, neļaut veselības pārbaudēm nonāvēt Redis pusceļā un padarīt nākamo ielādi īsāku.
$ redis-cli GET user:42
(error) LOADING Redis is loading the dataset in memory
Kad Redis ielādē datus un kas joprojām strādā
Ir divi bieži brīži:
- Servera starts. Ja persistence ir ieslēgta, Redis pirms klientu apkalpošanas nolasa RDB failu vai AOF. Mūsu pieredzē daži simti MB ielādējas sekundēs, bet desmitiem GB var aizņemt minūtes; precīzs laiks ir atkarīgs no diska ātruma, CPU un datu tipiem.
- Replikas pilnā sinhronizācija. Kad replika nevar turpināt replikāciju inkrementāli, tā saņem pilnu kopiju no galvenā servera. Ar noklusējumu
repl-diskless-load disabledtā vispirms saglabā RDB diskā, tad izdzēš vecos datus un ielādē jauno failu. Šīs ielādes laikā replika atbild ar LOADING.
Pati pārbaude atrodas failā server.c: kamēr iestatīts server.loading, jebkura komanda bez karodziņa CMD_LOADING tiek noraidīta ar šo kļūdu. Kurām komandām karodziņš ir, nosaka commands.def, un sarakstā ir daži pārsteigumi:
- Strādā ielādes laikā:
INFO,ROLE,CONFIG GET,SHUTDOWN,AUTH,HELLO,SELECT,CLIENTapakškomandas, piemēram,LISTunKILL, un Pub/Sub komandas. - Tiek noraidītas: visas parastās datu komandas (
GET,SETun pārējās), kā arīPING.PINGnav karodziņaCMD_LOADING, tāpēc veselības pārbaude, kas balstās uz to, visu ielādes laiku redz kļūdu.
Valkey darbojas tāpat. Tā server.c veido to pašu kļūdu ar servera nosaukumu tajā, un PING tur ir tie paši karodziņi.
Cik ilgi tas prasīs?
Tā kā INFO ielādes laikā strādā, Redis pats pasaka savu progresu:
Izvades piemērs (skaitļi ir ilustratīvi):
$ redis-cli INFO persistence | grep -E '^(async_)?loading'
loading:1
async_loading:0
loading_start_time:1762573620
loading_total_bytes:9663676416
loading_rdb_used_mem:0
loading_loaded_bytes:4187593113
loading_loaded_perc:43.33
loading_eta_seconds:131
INFO dokumentācija apraksta loading kā karodziņu, ka notiek dump faila ielāde. Kamēr tā notiek, parādās lauki loading_*: sākuma laiks, kopējie un ielādētie baiti, procenti un ETA. ETA failā server.c ir vienkārša ekstrapolācija no pagājušā laika un atlikušajiem baitiem, tāpēc uztveriet to kā aplēsi. Tā pietiek, lai atbildētu uz jautājumu "sekundes vai pusstunda?", kad kāds gaida uz jums.
Žurnāls rāda, cik ilgi ilga iepriekšējās ielādes. Tieši ar šo skaitli jāplāno:
# servera starts
* DB loaded from disk: 228.415 seconds
* DB loaded from append only file: 311.902 seconds (AOF)
* Done loading RDB, keys loaded: ..., keys expired: ...
# replikas pilnā sinhronizācija
* MASTER <-> REPLICA sync: receiving ... bytes from master to disk
* MASTER <-> REPLICA sync: Loading DB in memory
Ja starti kļūst arvien lēnāki, datu kopa aug vai disks zem tās ir lēns. Abas lietas vērts zināt pirms nākamā restarta, nevis tā laikā.
Kā veselības pārbaudes pārvērš ielādi dīkstāvē
Šis ir gadījums, kas dažas ielādes minūtes pārvērš stundām ilgā dīkstāvē. Liveness pārbaude, kas palaiž redis-cli PING un gaida PONG, ielādes laikā neizdodas. Kubernetes vidē neizdevusies liveness pārbaude restartē konteineru. Jaunais process sāk ielādi no sākuma, pārbaude atkal neizdodas, un Redis nekad nepabeidz. Tas pats notiek ar jebkuru uzraudzības rīku vai orķestrētāju, kas restartē "neveselus" procesus.
Kubernetes dokumentācijā ir pareizais rīks: ja konfigurēta startup pārbaude, liveness un readiness pārbaudes netiek palaistas, līdz tā izdodas. Dodiet Redis startup pārbaudi, kas atbilst tā reālajam ielādes laikam, un liveness pārbaudi veidojiet tā, lai tā pieņem LOADING:
startupProbe: # dod Redis laiku ielādei; liveness gaida uz to
exec:
command: ["sh", "-c", "redis-cli INFO persistence | grep -q '^loading:0'"]
periodSeconds: 10
failureThreshold: 90 # līdz ~15 minūtēm; pielāgojiet reālajam ielādes laikam
livenessProbe: # "dzīvs" arī ielādes laikā pēc vēlāka restarta
exec:
command: ["sh", "-c", "redis-cli PING | grep -qE 'PONG|LOADING'"]
readinessProbe: # nekādas slodzes, kamēr dati nav ielādēti
exec:
command: ["sh", "-c", "redis-cli PING | grep -q PONG"]
- Startup pārbaude gaida
loading:0. Tās kopējam laikam (periodSecondsreizfailureThreshold) jābūt garākam par sliktāko ielādes laiku no žurnāliem, ar rezervi. - Liveness pieņem
LOADINGkā dzīvu. Process, kas vispār atbild, nav uzkāries. - Readiness prasa
PONG, tāpēc klientu slodze netiek novirzīta uz instanci bez datiem.
Ārpus Kubernetes izmantojiet to pašu noteikumu izvietošanas skriptos: gaidiet loading:0, pirms sūtāt slodzi vai restartējat nākamo mezglu.
#!/bin/sh
# gaidiet, līdz Redis pabeidz ielādi, tad turpiniet
until redis-cli INFO persistence | grep -q '^loading:0'; do
redis-cli INFO persistence | grep -E '^loading_(loaded_perc|eta_seconds)'
sleep 5
done
echo "Redis is ready"
Ko redz klienti
Klientu bibliotēkas LOADING uztver kā atsevišķu kļūdas veidu. Piemēram, redis-py savā atbilžu parserī prefiksu LOADING piesaista BusyLoadingError, kas ir ConnectionError apakšklase. Tāpēc to ir viegli apstrādāt apzināti: atkārtot ar pieaugošu pauzi ierobežotu laiku vai, ja Redis ir kešatmiņa, izmantot primāro datu avotu. Ko jūs negribat, ir ciešs atkārtojumu cikls no katras lietotnes instances, kas bombardē serveri, kamēr tas ielādē datus.
loading_loaded_perc. Ja skaitlis kustas, restarts izmet progresu un sāk no jauna. Tikai tad, ja procenti ilgi nemainās un žurnālā nav progresa, kaut kas patiešām nav kārtībā.Kā padarīt nākamo ielādi īsāku
- Dodiet priekšroku RDB formāta ielādei. RDB ielāde parasti ir ātrāka nekā tīra AOF atskaņošana. Ja izmantojat AOF, paturiet
aof-use-rdb-preamble yes, kas ir noklusējums; redis.conf saka, ka RDB formāts bāzes failam vienmēr ir ātrāks un efektīvāks. Kompromisus apskata mūsu ceļvedis par RDB un AOF persistenci. - Turiet datu kopu godīgu. Ielādes laiks aug līdz ar to, kas ir atmiņā. Atslēgas, kam vajadzēja beigties, aizmirstas lielas atslēgas un neierobežotas kolekcijas katrā restartā maksā sekundes.
- Ātrs lokāls disks. Liels RDB lēnā tīkla krātuvē ielādējas lēni. Diska pārbaude atklāj arī saistīto kļūmi no mūsu raksta par MISCONF, kad Redis vispār nevar ierakstīt savus momentuzņēmumus.
- Restartu laikā apkalpojiet no replikas. Ar Sentinel vai Cluster pirms galvenā servera restarta veiciet failover uz ielādētu repliku, nevis lieciet klientiem gaidīt aukstu startu.
- Izvairieties no nevajadzīgām pilnām sinhronizācijām. Replikācijas backlog, kas ir par mazu laikam, kamēr replika ir atvienota, piespiež pilnu atkārtotu sinhronizāciju, un katra pilnā sinhronizācija nozīmē vēl vienu LOADING periodu replikā.
Replikām ar Redis 7.0 un jaunāku ir vēl viena iespēja. Ar repl-diskless-load swapdb replika parsē jaunos datus tieši no socket, vienlaikus turpinot apkalpot pašreizējo datu kopu. 7.0 redis.conf norāda, ka tas neattiecas uz gadījumiem, kad replika nevar atpazīt galveno serveri kā tādu, kam ir datu kopa no tās pašas replikācijas vēstures, un ka vajag pietiekami daudz atmiņas abām kopijām, citādi riskējat ar OOM kill. Šādas ielādes laikā INFO rāda async_loading:1, un tiek noraidītas tikai komandas, kas atzīmētas kā nedrošas asinhronajai ielādei.
# replika, Redis 7.0+: turpiniet apkalpot veco datu kopu pilnās sinhronizācijas laikā
repl-diskless-load swapdb
# vajag atmiņu vecajai un jaunajai datu kopai vienlaikus
Galvenās atziņas
- LOADING nozīmē, ka Redis pēc starta vai pilnas atkārtotas sinhronizācijas lasa savus datus atmiņā. Tas ir gaidīšanas stāvoklis, nevis kļūme.
INFO persistenceielādes laikā strādā un rāda procentus un ETA;PINGnestrādā.- Veselības pārbaudes, kas prasa
PONG, var restartēt Redis ciklā. Izmantojiet startup pārbaudi, LOADING pieņemošu liveness pārbaudi un stingru readiness pārbaudi. - Nekad nerestartējiet Redis, kura
loading_loaded_percjoprojām aug. - Īsākas ielādes nāk no RDB formāta failiem, kompaktas datu kopas, ātriem diskiem, failover uz replikām un mazāk pilnām sinhronizācijām;
swapdbversijā 7.0+ var paslēpt replikas resinhronizāciju, ja pietiek atmiņas.