Augsts Redis mem_fragmentation_ratio ir viens no biežākajiem atmiņas brīdinājumiem un viens no visbiežāk pārprastajiem. Šis skaitlis salīdzina to, ko redz operētājsistēma, ar to, ko Redis uzskata par piešķirtu. Vērtība 1,5 uz 30 GB instances var nozīmēt 10 GB reālas izšķērdības, nekaitīgu vakardienas maksimuma atlikumu vai uzskaites efektu, kam nav nekāda sakara ar jūsu datiem. Vērtība zem 1 ir vēl sliktāka: parasti tas nozīmē, ka kodols daļu Redis ir izspiedis uz swap. Lūk, kā to pareizi nolasīt un kas jādara katrā gadījumā.
Ko rādītājs patiesībā mēra
INFO memory definē mem_fragmentation_ratio kā attiecību starp used_memory_rss (cik RAM process aizņem operētājsistēmas skatījumā) un used_memory (cik Redis ir piešķīris caur savu alokatoru). Dokumentācija skaidri saka, ka tajā ietilpst ne tikai fragmentācija, bet arī citas procesa virsizmaksas, kods, koplietojamās bibliotēkas un steks.
Sāciet, apskatot visu kopā:
redis-cli INFO memory | grep -E '^(used_memory|used_memory_rss|used_memory_peak|mem_fragmentation_ratio|mem_fragmentation_bytes|allocator_frag_ratio|allocator_frag_bytes|allocator_rss_ratio|rss_overhead_ratio|mem_allocator):'
redis-cli MEMORY DOCTOR
Kopš Redis 4.0 MEMORY DOCTOR arī sniedz īsu, cilvēkam saprotamu pārskatu ar ieteikumiem. Pēc tam lasiet skaitļus šādā secībā:
mem_fragmentation_bytesir absolūtā starpība. Dokumentācijā norādīts, ka, ja tā ir tikai daži megabaiti, pat attiecība 1,5 vai vairāk nav problēma. Mazām instancēm augsta attiecība bieži ir tieši šī iemesla dēļ.allocator_frag_ratiounallocator_frag_bytessalīdzina aktīvās alokatora lapas ar faktiski piešķirto. Dokumentācija to sauc par patieso (ārējās) fragmentācijas rādītāju.allocator_rss_ratioparāda lapas, kuras alokators tur, bet var un, visticamāk, drīz atdos atpakaļ operētājsistēmai.rss_overhead_ratioaptver RSS, kas nav saistīts ar alokatoru vai kaudzi.
Ja allocator_frag_ratio ir tuvu 1, bet mem_fragmentation_ratio ir augsts, jūs neskatāties uz fragmentāciju parastajā nozīmē.
1. cēlonis: pagātnes maksimums, nevis fragmentācija
Biežākais skaidrojums ir aprakstīts Redis atmiņas optimizācijas ceļvedī: Redis ne vienmēr atdod atmiņu operētājsistēmai, kad atslēgas tiek dzēstas. Ja instance izauga līdz 5 GB un pēc tam tika dzēsti 2 GB atslēgu, RSS, visticamāk, paliks ap 5 GB, kamēr used_memory nokritīsies līdz 3 GB. Atbrīvotās lapas bieži dala vietu ar atslēgām, kas vēl eksistē, tāpēc alokators nevar tās atdot.
Šī atmiņa nav zaudēta. Kad pienāk jaunas atslēgas, alokators atkārtoti izmanto atbrīvoto vietu, un RSS nemainās, līdz dati pārsniedz veco izmēru. Salīdziniet used_memory_peak ar used_memory_rss: ja RSS ir tuvu maksimumam, attiecība atspoguļo vēsturi, nevis problēmu. Ceļvedis pats izdara praktisko secinājumu: plānojiet atmiņu maksimālajam lietojumam un neuzticieties fragmentācijas attiecībai pēc liela maksimuma.
Tipiski izraisītāji ir masveida dzēšana, pakešuzdevums, kas uz dažām stundām piepildīja kešatmiņu, vai liels izlikšanas vilnis. Kā izlikšana un maxmemory mijiedarbojas, skaidrojām rakstā Redis OOM un izlikšanas politikas.
2. cēlonis: īsta fragmentācija
Īsta ārējā fragmentācija rodas, kad slodze nepārtraukti piešķir un atbrīvo dažāda izmēra vērtības: virknes, kas aug un sarūk, daudz atslēgu ar īsu TTL, jaucējtabulas un saraksti, kas pastāvīgi maina izmēru. Alokatoram paliek daudz daļēji izmantotu lapu. To redz kā augstu allocator_frag_ratio kopā ar lielu allocator_frag_bytes, un tas nepazūd, kad datu kopa atkal pieaug.
Ņemiet vērā, ka maxmemory ierobežo to, ko Redis piešķir datiem; atmiņas ceļvedis saka, ka Redis piešķir ne vairāk par šo apjomu, izņemot nelielus papildu piešķīrumus. Fragmentācija nāk klāt. Serverim ar maxmemory 24gb un īstu fragmentāciju 1,4 vajag daudz vairāk nekā 24 GB RAM, un OOM killer neinteresē, ko saka maxmemory.
3. cēlonis: attiecība zem 1 nozīmē swap
Ja used_memory ir lielāks par used_memory_rss, dokumentācija saka, ka daļu Redis atmiņas operētājsistēma ir izspiedusi uz swap, un jārēķinās ar ievērojamu aizturi. Tas ir bīstamais gadījums, un to viegli palaist garām, jo brīdinājumus parasti iestata tikai augstām vērtībām. Aiztures ceļvedis parāda, kā to apstiprināt:
redis-cli INFO server | grep process_id
grep Swap: /proc/<pid>/smaps | awk '{s+=$2} END {print s " kB swapped"}'
vmstat 1 # ne-nulles si/so kolonnas nozīmē, ka swap notiek tieši tagad
Risinājums ir mazāks atmiņas spiediens, nevis Redis pielāgošana: vairāk RAM, zemāks maxmemory vai citu atmiņu prasīgu procesu pārvietošana no servera.
Aktīvā defragmentācija
Redis 4.0 ieviesa aktīvo defragmentāciju, kas pārvieto vērtības kompaktos atmiņas apgabalos, kamēr serveris turpina darbu. Saskaņā ar redis.conf tā pēc noklusējuma ir izslēgta un darbojas tikai ar Redis komplektā iekļauto jemalloc kopiju, kas ir noklusējums Linux būvējumiem. To var ieslēgt darba laikā:
# pārbaudiet, vai serveris izmanto jemalloc
redis-cli INFO memory | grep mem_allocator
# ieslēdziet darba laikā (sliekšņiem paliek noklusējuma vērtības)
redis-cli CONFIG SET activedefrag yes
redis-cli CONFIG GET active-defrag-*
# sekojiet progresam
redis-cli INFO memory | grep -E 'allocator_frag_ratio|active_defrag_running'
redis-cli INFO stats | grep -E 'active_defrag_(hits|misses|key_hits|key_misses)'
Noklusējuma vērtības Redis 7.4 un 8.0 un Valkey 8.1 ir vienādas:
active-defrag-ignore-bytes 100mb: nesākt, ja fragmentācijas zudumi ir mazāki par 100 MB;active-defrag-threshold-lower 10: sākt pie 10% fragmentācijas;active-defrag-threshold-upper 100: maksimālā piepūle pie 100%;active-defrag-cycle-min 1unactive-defrag-cycle-max 25: minimālā un maksimālā piepūle procentos no CPU;active-defrag-max-scan-fields 1000: cik kopas, jaucējtabulas, sakārtotas kopas vai saraksta lauku apstrādā no galvenās vārdnīcas skenēšanas.
Valkey 8.1 pievieno active-defrag-cycle-us (noklusējums 500 mikrosekundes), katra defragmentācijas cikla ilgumu, kas nosaka ietekmi uz klientu komandu aizturi. Paši konfigurācijas faili iesaka neaiztikt noklusējuma vērtības, ja nezināt, ko maināt, un ieslēgt funkciju tikai tad, ja fragmentācija tiešām ir.
Ir arī MEMORY PURGE, kas lūdz jemalloc atbrīvot netīrās lapas. Tas var samazināt allocator_rss_bytes, bet neko nekompaktē, tāpēc īstu fragmentāciju nenovērš.
Lielas instances: kas mainās
- Defragmentācija maksā aizturi. Defragmentācija strādā galvenajā pavedienā īsos ciklos, un ar noklusējuma maksimumu 25% CPU tā konkurē ar klientu komandām. Noslogotā 50 GB instancē tās darbības laikā sekojiet komandu aizturei un samaziniet
active-defrag-cycle-max, ja cieš p99. Pirmo reizi ieslēdziet to klusākā periodā. - Tas prasa laiku. Process pakāpeniski iet cauri atslēgu telpai. Desmitiem gigabaitu gadījumā rēķinieties ar ilgu darbu, nevis minūtēm; sekojiet
active_defrag_hitsunallocator_frag_ratio, nevis gaidiet pēkšņu kritumu. - Restarts ir otrs risinājums, bet ne bezmaksas. Konfigurācijas failā norādīts, ka bez aktīvās defragmentācijas fragmentācijas samazināšanai parasti vajag restartu vai datu izdzēšanu un atkārtotu ielādi. Lielai instancei tas nozīmē minūtes ielādes no RDB vai AOF. Drošāks ceļš ir plānota pārslēgšana: ļaujiet replikai pārņemt darbu un restartējiet veco primāro serveri. Replika, kas tikko ielādējusi pilnu datu kopiju, parasti sāk ar nelielu fragmentāciju.
- Fork un copy-on-write. RDB momentuzņēmumi un AOF pārrakstīšana veic procesa fork. Fork laikā lapas, kurās raksta, tiek kopētas, tāpēc RSS kādu laiku var būt krietni lielāks par
used_memory. Ja ieslēgtas caurspīdīgās milzu lapas (THP), aiztures ceļvedis brīdina, ka tas var pārvērsties gandrīz visas procesa atmiņas kopēšanā ar lielu aizturi un atmiņas patēriņu; tas liek THP izslēgt. Fork izmaksas aplūkojām rakstā Redis persistence: RDB pret AOF. - Rezerve. Plānojiet serveri maksimālajam datu apjomam, plus fragmentācijai, plus copy-on-write persistences laikā, plus replikācijas un klientu buferiem. Pareizā rezerve ir atkarīga no rakstīšanas intensitātes persistences laikā: nomēriet RSS BGSAVE laikā reālas slodzes apstākļos.
Mūsu īkšķa likums: brīdiniet par mem_fragmentation_bytes un par attiecību zem 1, nevis tikai par attiecību virs 1,5. Pirms ieslēdzat defragmentāciju, pārbaudiet allocator_frag_ratio. Ja tas ir tuvu 1, "fragmentācija" ir pagātnes maksimums vai virsizmaksas, un defragmentācija nepalīdzēs.
Kontrolsaraksts, kad iedarbojas brīdinājums
- Pārbaudiet
mem_fragmentation_bytes: vai zudumi ir pietiekami lieli, lai būtu svarīgi? - Ja attiecība ir zem 1, vispirms pārbaudiet swap failā
/proc/<pid>/smapsun arvmstat. - Salīdziniet
used_memory_rssarused_memory_peak, lai saprastu, vai tas ir pagātnes maksimums. - Nolasiet
allocator_frag_ratiounallocator_frag_bytes, lai redzētu īsto fragmentāciju. - Pārliecinieties, ka
mem_allocatorir jemalloc, tad klusākā periodā ieslēdzietactivedefragun sekojiet aizturei. - Ja defragmentācija nav pietiekama vai nav pieejama, plānojiet pārslēgšanu uz repliku un restartējiet veco primāro serveri.
- Pārskatiet izmēru: maksimālie dati plus fragmentācija plus fork virsizmaksas.
Galvenās atziņas
mem_fragmentation_ratioir RSS, dalīts arused_memory, un ietver vairāk nekā fragmentāciju.- Patiesais fragmentācijas rādītājs ir
allocator_frag_ratio; mazi absolūtie zudumi nav problēma pat pie augstas attiecības. - Augsta attiecība pēc masveida dzēšanas bieži ir pagātnes maksimums. Atmiņa tiek atkārtoti izmantota, kad dati atkal aug.
- Attiecība zem 1 norāda uz swap un nopietnu aizturi.
- Aktīvā defragmentācija pēc noklusējuma ir izslēgta, prasa jemalloc un lielās instancēs patērē galvenā pavediena CPU.
- Plānojiet maksimumam plus fragmentācijai plus copy-on-write, nevis tikai
maxmemory.