Redis'in ne kadar bellek kullandığını görmenin üç düzeyi vardır: sunucunun tamamı için INFO memory ve MEMORY STATS, tek bir anahtar için MEMORY USAGE anahtar, tüm anahtar uzayında en büyük anahtarları bulmak için redis-cli --bigkeys ve --memkeys. Bunlara ek olarak OBJECT ENCODING bir değerin bellekte hangi iç kodlamayla saklandığını, MEMORY DOCTOR ise bellekle ilgili sorunları ve olası çözümleri bildirir.

Bu yazıda INFO memory alanlarının ne anlama geldiğini ve hangi farkların sorun işareti olduğunu, MEMORY komut ailesini, kodlamaları ve büyük anahtarları redis-cli ile taramayı anlatıyoruz. Bellek dolduğunda Redis'in ne yaptığı, yani maxmemory ve çıkarma politikaları maxmemory ve eviction yazısında ayrı ele alınıyor. Serinin tamamı için Redis öğrenme rehberi sayfasına bakın.

INFO memory: temel alanlar

INFO memory: temel alanlar: used_memory, used_memory_human, used_memory_rss, used_memory_peak

INFO memory bölümü sunucunun bellek durumunu tek bakışta verir. Komutun çıktısı sürüme göre alan ekleyip çıkarabilir; belge, bilinmeyen alanları atlayan bir ayrıştırma önerir. En çok bakacağınız alanlar şunlardır:

AlanAnlamı
used_memoryRedis'in kendi ayırıcısıyla (libc, jemalloc gibi) ayırdığı toplam bayt
used_memory_humanAynı değerin okunabilir biçimi
used_memory_rssİşletim sisteminin gördüğü, Redis'e ayrılmış bayt (top ve ps değeri)
used_memory_peakRedis'in ulaştığı en yüksek bellek kullanımı
used_memory_overheadİç veri yapılarını yönetmek için ayrılan toplam ek yük
used_memory_startupBaşlangıçta tüketilen bellek
used_memory_datasetVeri kümesinin boyutu; used_memory eksi used_memory_overhead
maxmemory, maxmemory_policyBellek sınırı ve çıkarma politikası
mem_fragmentation_ratioused_memory_rss ile used_memory oranı
allocator_frag_ratioGerçek (dış) parçalanma ölçüsü
mem_clients_normalNormal istemcilerin kullandığı bellek
mem_not_counted_for_evictEviction hesabına girmeyen tamponlar

Belgeye göre ideal durumda used_memory_rss, used_memory değerinden yalnızca biraz yüksektir. RSS çok daha büyükse bu, dış bellek parçalanmasına işaret edebilir ve allocator_frag_ratio ile allocator_frag_bytes alanlarıyla değerlendirilir. Tersi, yani used_memory değerinin RSS'ten çok büyük olması, Redis belleğinin bir kısmının işletim sistemi tarafından takas alanına (swap) atıldığı anlamına gelir; bu durumda ciddi gecikmeler beklemelisiniz.

mem_fragmentation_ratio değerini yorumlarken dikkatli olun. Belge bu oranın yalnızca parçalanmayı değil, diğer süreç ek yüklerini, kod, paylaşılan kütüphaneler ve yığın gibi kalemleri de içerdiğini belirtir. Toplam parçalanma baytı küçükse (birkaç megabayt), 1,5 ve üzeri gibi yüksek bir oran bir sorun göstergesi değildir. Bu yüzden oranla birlikte mem_fragmentation_bytes değerine de bakın.

Bir başka yaygın kafa karışıklığı, silinen verinin belleğinin hemen işletim sistemine dönmemesidir. Redis belleği boşalttığında bellek ayırıcıya döner; ayırıcı bunu sisteme geri verebilir de vermeyebilir de. Bu yüzden used_memory ile işletim sisteminin bildirdiği kullanım arasında fark olabilir; belge bu durumu kontrol etmek için used_memory_peak değerinin genellikle yararlı olduğunu söyler. Yüksek RSS çoğu zaman geçmişteki bir bellek sıçramasının sonucudur.

Silme işleminin kendisi de anında bitmeyebilir. UNLINK ya da ASYNC seçeneğiyle çalıştırılan FLUSHDB ve FLUSHALL, nesneleri arka planda serbest bırakır. Serbest bırakılmayı bekleyen nesne sayısı INFO memory içindeki lazyfree_pending_objects, bu yolla serbest bırakılmış nesnelerin toplamı lazyfreed_objects alanında görünür. Büyük bir silme sonrasında belleğin bir süre yüksek kalması bu yüzden olağandır; önce bu sayacın sıfıra inmesini bekleyin. DEL ile UNLINK farkı anahtar ve keyspace yazısında.

MEMORY USAGE: tek bir anahtarın boyutu

MEMORY USAGE anahtar, bir anahtarın ve değerinin RAM'de saklanması için gereken bayt sayısını döndürür. Bu sayı veri ve yönetim ek yüklerinin toplamıdır; anahtar yoksa yanıt nil olur. Belgedeki örnekler Redis 7.2.0, 64 bit ve jemalloc ile alınmıştır; sizin sunucunuzda sürüme ve ayırıcıya göre farklı sayılar görebilirsiniz:

text
> SET "" ""
OK
> MEMORY USAGE ""
(integer) 56

Boş anahtar ve boş değer bile 56 bayt tutar. Bu baytların tamamı şimdilik ek yüktür: hiç veri saklanmamıştır ama sunucunun iç veri yapılarını (ayırıcının iç parçalanması dahil) korumak için gerekir. Daha uzun anahtar ve değerlerde kullanım asimptotik olarak doğrusal artar:

text
> SET foo bar
OK
> MEMORY USAGE foo
(integer) 56
> SET foo2 mybar
OK
> MEMORY USAGE foo2
(integer) 64
> SET foo3 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
OK
> MEMORY USAGE foo3
(integer) 160

Bu örnekten çıkacak pratik ders, çok sayıda küçük anahtarda ek yükün veri boyutunu geçebileceğidir. Örneğin üç baytlık bar değeri için 56 bayt harcanır. Milyonlarca küçük değer saklayacaksanız veri tipini ve anahtar yapısını bu ek yükü hesaba katarak seçmek, toplam belleği doğrudan etkiler; hash komutları hash yazısında, veri tipi seçimi veri tipi seçimi yazısında.

Hash, liste, küme gibi iç içe veri tiplerinde komut tüm elemanları tek tek ölçmez; SAMPLES sayı seçeneğiyle belirtilen sayıda iç değeri örnekler ve ortalamadan toplam boyutu tahmin eder. Varsayılan örnek sayısı 5'tir; tüm iç değerleri ölçmek için SAMPLES 0 verin. Büyük bir koleksiyonda SAMPLES 0 daha doğru ama daha pahalıdır. Redis 8.10 ile kompakt hash kodlamasıyla saklanan bir hash için raporlanan değer, paylaşılan kompakt hash şablonunun belleğinden anahtara düşen payı da (şablon boyutunun onu kullanan tüm anahtarlara eşit bölünmesi) içerir.

text
MEMORY USAGE kullanici:42
MEMORY USAGE siparisler:2026 SAMPLES 0

MEMORY STATS ve MEMORY DOCTOR

MEMORY STATS ve MEMORY DOCTOR: peak.allocated, total.allocated, startup.allocated, clients.normal

MEMORY STATS, sunucunun bellek kullanımını ölçüt adları ve değerlerinden oluşan iç içe bir dizi olarak döndürür. Ölçütlerin çoğu INFO memory alanlarının karşılığıdır, ancak bazıları ek ayrıntı verir:

MEMORY STATS ölçütüAnlamı
peak.allocatedEn yüksek bellek kullanımı (INFO used_memory_peak)
total.allocatedAyırıcıyla ayrılan toplam (INFO used_memory)
startup.allocatedBaşlangıç belleği (INFO used_memory_startup)
clients.normalTüm normal istemcilerin tampon ve bağlantı ek yükü
clients.slavesTüm replikaların ek yükü
aof.bufferAOF ile ilgili tamponların toplamı
lua.caches, functions.cachesLua betik ve fonksiyon önbelleklerinin ek yükü
dbXXXHer veritabanının ana ve süre sözlüklerinin ek yükü
overhead.totalTüm ek yüklerin toplamı (INFO used_memory_overhead)
keys.countTüm veritabanlarındaki toplam anahtar sayısı
keys.bytes-per-keydataset.bytes ile keys.count oranı
dataset.bytes, dataset.percentageVeri kümesinin boyutu ve toplam içindeki payı
fragmentationINFO mem_fragmentation_ratio karşılığı

keys.bytes-per-key, anahtar başına ortalama veri boyutunu verdiği için kapasite planlamasında kullanışlıdır: ortalamayı beklediğiniz anahtar sayısıyla çarparak kabaca bir büyüme tahmini yapabilirsiniz. MEMORY DOCTOR ise sunucunun yaşadığı bellek sorunlarını raporlayan ve olası çözümler öneren bir metin döndürür; ne zaman bakacağınızı bilmediğiniz durumlarda ilk adım olarak kullanışlıdır.

MEMORY MALLOC-STATS bellek ayırıcının iç istatistik raporunu verir, MEMORY PURGE ise kirli sayfaları temizleyerek ayırıcının bunları geri almasını dener ve OK döndürür. Belgeye göre her iki komut da şu anda yalnızca ayırıcı jemalloc olduğunda uygulanmıştır; diğer ayırıcılarda zararsız bir işlem yapmama (NOOP) olarak çalışır. Hangi ayırıcının kullanıldığını INFO memory içindeki mem_allocator alanından görürsünüz. INFO belgesi, allocator_resident değerinin MEMORY PURGE ile ya da kendiliğinden işletim sistemine bırakılabilecek sayfaları da içerdiğini belirtir.

OBJECT ENCODING: değer nasıl saklanıyor

Aynı veri tipi, boyutuna ve içeriğine göre farklı iç kodlamalarla saklanabilir; küçük değerler için yer tasarrufu sağlayan özel kodlamalar kullanılır. OBJECT ENCODING anahtar bu kodlamayı metin olarak döndürür; anahtar yoksa nil döner.

TipOlası kodlamalar
Stringraw, int (64 bit işaretli tamsayı), embstr (44 bayta kadar gömülü)
Listlistpack (Redis 7.0 ve sonrası küçük listeler), quicklist
Sethashtable, intset (yalnızca tamsayılı küçük kümeler), listpack (Redis 7.2 ve sonrası)
Hashhashtable, listpack (Redis 7.0 ve sonrası küçük hash'ler)
Sorted setskiplist, listpack (Redis 7.0 ve sonrası küçük kümeler)
Streamstream (listpack'lerden oluşan radix ağacı)

Eski sürümlerde listpack yerine ziplist görülür (Redis 6.2 ve öncesi). Özel kodlamalı bir değer, yer tasarruflu kodlamayı korumayı imkânsız kılan bir işlem yaptığınızda otomatik olarak genel kodlamaya dönüştürülür. Küçük kodlamaların sınırları hash-max-listpack-entries, set-max-intset-entries, zset-max-listpack-entries gibi ayarlardır; belgedeki CONFIG GET örneğinde hash ve set için 512, sorted set için 128 değerleri görünür. Bu ayarların okunması ve değiştirilmesi CONFIG GET, SET ve REWRITE yazısında.

text
SET sayac 12345
OBJECT ENCODING sayac
SADD etiketler 1 2 3
OBJECT ENCODING etiketler

Bu kendi örneğimizde sayac değeri 64 bitlik işaretli tamsayı aralığında olduğu için belgeye göre int kodlamasına uygundur; yalnızca tamsayılardan oluşan küçük etiketler kümesi ise intset kodlamasına adaydır. Kesin sonucu sunucunuzda komutu çalıştırarak görün. OBJECT FREQ ve OBJECT IDLETIME komutları ise anahtarların erişim bilgisini verir ve çıkarma politikasına bağlıdır; ayrıntı eviction yazısında.

redis-cli ile büyük anahtarları bulmak

Hangi anahtarın belleği şişirdiğini bilmiyorsanız redis-cli'nin anahtar uzayı analizi modları işe yarar. --bigkeys veri kümesini tarayıp her veri tipi için en büyük anahtarı (eleman sayısına göre) bulur ve tiplere göre özet çıkarır. Belgedeki örnek çıktı şöyledir:

bash
$ redis-cli --bigkeys

# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).

100.00% ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Keys sampled: 55

-------- summary -------

Total key length in bytes is 495 (avg len 9.00)

Biggest   list found "bikes:finished" has 1 items
Biggest string found "all_bikes" has 36 bytes
Biggest   hash found "bike:1:stats" has 3 fields
Biggest stream found "race:france" has 4 entries
Biggest    set found "bikes:racing:france" has 3 members
Biggest   zset found "racer_scores" has 8 members

1 lists with 1 items (01.82% of keys, avg size 1.00)
16 strings with 149 bytes (29.09% of keys, avg size 9.31)
1 MBbloomCFs with 0 ? (01.82% of keys, avg size 0.00)
1 hashs with 3 fields (01.82% of keys, avg size 3.00)
3 streams with 8 entries (05.45% of keys, avg size 2.67)
2 TDIS-TYPEs with 0 ? (03.64% of keys, avg size 0.00)
1 TopK-TYPEs with 0 ? (01.82% of keys, avg size 0.00)
2 sets with 5 members (03.64% of keys, avg size 2.50)
1 CMSk-TYPEs with 0 ? (01.82% of keys, avg size 0.00)
2 zsets with 11 members (03.64% of keys, avg size 5.50)
25 ReJSON-RLs with 0 ? (45.45% of keys, avg size 0.00)

--bigkeys eleman ya da bayt sayısına bakar; gerçek bellek kullanımını görmek için --memkeys kullanın. Bu mod aynı taramayı yapar ama her tip için en büyük anahtarı bellekteki bayt boyutuna göre raporlar. Belgedeki --memkeys örneğinde, --bigkeys çıktısında "0 ?" olarak görünen MBbloomCF tipindeki bikes:models anahtarının 1.048.680 bayt ile en büyük anahtar olduğu ortaya çıkar; eleman sayısı ile bellek boyutunun aynı şey olmadığını iyi gösteren bir örnektir. --keystats ise iki modu birleştirir ve en büyük anahtarların listesi, tip başına en büyük boyut ve boyut yüzdelik dağılımı gibi ek bilgiler verir; --top <n> ile kaç anahtar listeleneceğini seçebilirsiniz (varsayılan 10).

Bu modlar SCAN komutunu kullandığı için yoğun bir sunucuda da işlemleri engellemeden çalıştırılabilir. Yükü azaltmak için -i seçeneği her SCAN çağrısı arasında belirtilen kesirli saniye kadar bekler; belgeye göre -i 0.01 programı belirgin biçimde yavaşlatır ama sunucu üzerindeki yükü ihmal edilebilir düzeye indirir. --bigkeys ve --memkeys cluster replikalarında da çalışır, bu da analizi birincil sunucudan uzak tutmanızı sağlar. SCAN ile KEYS arasındaki fark SCAN ve KEYS yazısında, redis-cli'nin diğer modları redis-cli kullanımı yazısında.

bash
redis-cli --memkeys -i 0.01
redis-cli --keystats --top 20

INFO keysizes: boyut dağılımı

INFO keysizes bölümü, veritabanı başına string, list, set, hash ve sorted set tipleri için anahtar boyutlarının dağılımını taban 2 logaritmik bir histogramla verir. Satırlar db0_distrib_strings_sizes ve db0_distrib_hashes_items gibi adlarla gelir; her aralığa düşen anahtar sayısını gösterir. Tam tarama yapmadan "çok büyük koleksiyonlarım var mı" sorusuna hızlı bir cevap almak için kullanışlıdır.

Uygulamalı örnek: belleği şişen bir sunucuyu incelemek

Önbellek sunucunuzun belleği beklenmedik biçimde arttı diyelim. Aşağıdaki sıra belgelerdeki komut ve alanlarla kurulmuş kendi teşhis akışımızdır.

bash
redis-cli INFO memory
redis-cli MEMORY DOCTOR
redis-cli --memkeys -i 0.01
redis-cli MEMORY USAGE oturum:buyuk-anahtar SAMPLES 0
redis-cli OBJECT ENCODING oturum:buyuk-anahtar

İlk adımda used_memory_dataset ile used_memory_overhead değerlerini karşılaştırın. Artış veri kümesindeyse sorun anahtarlardadır; ek yükteyse mem_clients_normal gibi alanlar istemci tamponlarının büyüdüğünü gösterebilir ve bağlantı tarafını CLIENT LIST yazısındaki gibi incelemeniz gerekir. used_memory_rss değeri used_memory değerinden çok yüksekse parçalanmaya bakın. Veri tarafında --memkeys en büyük anahtarları listeler; şüpheli anahtarın gerçek boyutunu SAMPLES 0 ile ölçüp kodlamasına bakarsınız. Küçük kodlamadan genel kodlamaya geçmiş büyük bir hash ya da sınırsız büyüyen bir liste genellikle bu adımda ortaya çıkar; sınırlı liste deseni için list yazısındaki LTRIM kullanımına bakabilirsiniz.

Sık yapılan hatalar

Sık yapılan hatalar: used_memory ile RSS'i aynı sanmak, Küçük toplam parçalanmada yüksek mem_fragmentation_ratio değerine alarm vermek..., MEMORY USAGE sonucunu kesin sanmak...
  • used_memory ile RSS'i aynı sanmak: biri Redis'in ayırdığı, diğeri işletim sisteminin gördüğü bellektir; aradaki fark parçalanma ya da geri verilmemiş bellek olabilir.
  • Küçük toplam parçalanmada yüksek mem_fragmentation_ratio değerine alarm vermek: belge birkaç megabaytlık farkta yüksek oranın sorun göstergesi olmadığını söyler.
  • MEMORY USAGE sonucunu kesin sanmak: iç içe tiplerde varsayılan 5 örnekle tahmin edilir; kesin değer için SAMPLES 0 gerekir.
  • --bigkeys çıktısını bellek boyutu sanmak: bu mod eleman sayısına bakar; bellek için --memkeys kullanın.
  • Büyük anahtarları bulmak için üretimde KEYS * çalıştırmak: redis-cli'nin tarama modları SCAN ile engellemeden çalışır.

Sık Sorulan Sorular

Anahtarları sildim ama bellek düşmedi, neden?

Redis boşalttığı belleği ayırıcıya verir; ayırıcı bunu işletim sistemine hemen geri vermeyebilir. Bu yüzden RSS yüksek kalabilir. jemalloc kullanıyorsanız MEMORY PURGE kirli sayfaların geri alınmasını deneyebilir.

Tek bir anahtarın ne kadar bellek kullandığını nasıl öğrenirim?

MEMORY USAGE anahtar kullanın. Yanıt bayt cinsinden tamsayıdır ve anahtar yoksa nil döner. Koleksiyonlarda kesin değer için SAMPLES 0 ekleyin.

mem_fragmentation_ratio kaç olmalı?

Belge sabit bir hedef vermez; RSS'in used_memory değerinden biraz yüksek olmasının ideal olduğunu, oranın başka ek yükleri de içerdiğini ve küçük bayt farklarında yüksek oranın sorun olmadığını söyler. Gerçek dış parçalanma için allocator_frag_ratio değerine bakın.

En büyük anahtarları sunucuyu yormadan nasıl bulurum?

redis-cli --memkeys ya da --bigkeys kullanın ve -i 0.01 gibi bir bekleme ekleyin. Bu modlar SCAN kullanır ve cluster replikalarında da çalışır.

OBJECT ENCODING neden beklediğim kodlamayı göstermiyor?

Kodlama değerin boyutuna ve içeriğine bağlıdır ve sınır aşıldığında genel kodlamaya otomatik geçer. Ayrıca kodlama eşiklerini değiştirmek mevcut anahtarlara hemen değil, bir sonraki yazmada uygulanır.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: Redis öğrenme rehberi · maxmemory ve eviction politikaları · INFO komutu ve sunucu izleme · Redis veri tipi seçimi · SCAN ve KEYS farkı