Redis'te maxmemory veri için kullanılabilecek en fazla belleği, maxmemory-policy ise bu sınıra ulaşıldığında ne olacağını belirler. Varsayılan politika noeviction olduğu için sınır dolunca Redis hiçbir anahtarı silmez, yeni veri ekleyen komutlara OOM hatası döndürür. Redis'i önbellek olarak kullanıyorsanız çoğu durumda allkeys-lru gibi bir çıkarma (eviction) politikası seçersiniz; Redis de sınır aşıldığında en az kullanılan anahtarları silerek yer açar.
Bu yazıda maxmemory ayarının nasıl çalıştığını, replikasyon ve kalıcılık tamponlarının neden hesaba katılmadığını, on politikanın her birinin ne yaptığını, yaklaşık LRU, LFU ve Redis 8.6 ile gelen LRM algoritmalarını, doğru politikayı seçmek için hangi INFO alanlarına bakacağınızı ve OOM hatasını anlatıyoruz. Önbelleğin genel kavramları için önbellek nedir yazısına, serinin tamamı için Redis öğrenme rehberi sayfasına bakın.
maxmemory nasıl çalışır
Önbellekteki girdiler genellikle kalıcı olarak başka yerde saklanan verinin kopyalarıdır; bu yüzden bellek dolduğunda onları atmak çoğu zaman güvenlidir, gerekirse yeniden önbelleğe alınırlar. Redis bunu otomatik yapar: bir istemci önbelleğe veri ekleyen yeni bir komut çalıştırdığında Redis bellek kullanımını kontrol eder, kullanım sınırın üzerindeyse seçili politikaya göre anahtarları siler ve toplam kullanım sınırın altına inene kadar devam eder.
Sınır redis.conf içinde ya da çalışırken CONFIG SET ile verilir. Belgedeki örnek 100 megabaytlık bir sınırdır:
maxmemory 100mb> CONFIG SET maxmemory 100mbmaxmemory değerini sıfır yapmak veri kümesi için bellek sınırı istemediğiniz anlamına gelir; 64 bit sistemlerde varsayılan davranış budur, 32 bit sistemler ise örtük olarak 3 GB sınır kullanır. Belge önemli bir uyarı da yapar: çok veri ekleyen tek bir komut (örneğin sonucunu yeni bir anahtara yazan büyük bir küme kesişimi) sınırı geçici olarak büyük farkla aşabilir. Çalışırken ayar değiştirmenin genel kuralları CONFIG GET, SET ve REWRITE yazısında.
Replikasyon ve kalıcılık tamponları sayılmaz
Sunucu replikasyon ya da kalıcılık kullanıyorsa Redis, replikalara ya da AOF dosyasına yazılmayı bekleyen güncellemeleri tutmak için bir miktar RAM'i tampon olarak kullanır. Bu tamponun belleği, eviction gerekip gerekmediğine karar verirken maxmemory ile karşılaştırılan toplama dahil edilmez. Nedeni bir geri besleme döngüsünü önlemektir: anahtar çıkarmanın kendisi de tampona eklenmesi gereken güncellemeler üretir; bu güncellemeler kullanılan belleğe sayılsaydı, çıkarmayla kazanılan bellek hemen tampona gider, bu da daha fazla çıkarmayı tetikler ve önbellekten gereksiz yere çok sayıda anahtar silinirdi.
Bu yüzden belge, replikasyon ya da kalıcılık kullanıyorsanız maxmemory değerini tamponlar için biraz RAM boş kalacak şekilde ayarlamanızı önerir; noeviction politikasında buna gerek yoktur. Tamponların o anki boyutu INFO memory bölümündeki mem_not_counted_for_evict alanında görünür. Değer zamanla değişse de, toplam RAM'den ne kadar düşmeniz gerektiğini tahmin etmek için kullanabilirsiniz.
Eviction politikaları

| Politika | Hangi anahtarlar aday | Nasıl seçer |
|---|---|---|
| noeviction | Hiçbiri | Silmez; veri ekleyen komutlar hata alır |
| allkeys-lru | Tüm anahtarlar | En uzun süredir kullanılmayan (LRU) |
| allkeys-lrm | Tüm anahtarlar | En uzun süredir değiştirilmeyen (LRM) |
| allkeys-lfu | Tüm anahtarlar | En seyrek kullanılan (LFU) |
| allkeys-random | Tüm anahtarlar | Rastgele |
| volatile-lru | Süresi (TTL) olan anahtarlar | LRU |
| volatile-lrm | Süresi olan anahtarlar | LRM |
| volatile-lfu | Süresi olan anahtarlar | LFU |
| volatile-random | Süresi olan anahtarlar | Rastgele |
| volatile-ttl | Süresi olan anahtarlar | Kalan süresi en kısa olan |
noeviction politikasında okuma komutları normal çalışmaya devam eder; yalnızca yeni veri ekleyen komutlar hata alır. Replikasyon kullanılıyorsa bu durum yalnızca birincil sunucu için geçerlidir. volatile- ile başlayan politikalar yalnızca süre atanmış anahtarlar arasından seçim yapar; hiçbir anahtarın süresi yoksa noeviction gibi davranırlar. Bu, beklenmedik OOM hatalarının en yaygın nedenlerinden biridir: politika volatile-lru olduğu hâlde uygulama anahtarlara süre vermiyordur. Süre atama komutları EXPIRE ve TTL yazısında anlatılıyor.
maxmemory 100mb
maxmemory-policy allkeys-lruHangi politikayı seçmeli

Belge politikanın uygulamanızın anahtarlara erişim biçimine uyması gerektiğini söyler ve şu temel kuralları verir:
- allkeys-lru: Anahtarların bir alt kümesine diğerlerinden çok daha sık erişilmesini bekliyorsanız. Pareto ilkesine göre bu çok yaygın bir durumdur; belge, başka bir tercih nedeniniz yoksa
allkeys-lrupolitikasını iyi bir varsayılan olarak önerir. - allkeys-lrm: Sık okunan veriyi korumak ama uzun süredir değiştirilmemiş veriyi çıkarmak istediğinizde. Okuma ağırlıklı iş yüklerinde, aktif olarak güncellenen veriyi yalnızca okunan veriden ayırmak için kullanışlıdır.
- allkeys-random: Tüm anahtarlara aşağı yukarı eşit sıklıkta erişilmesini bekliyorsanız, örneğin uygulama veri öğelerini tekrar eden bir döngüde okuyorsa.
- volatile-ttl: Kodunuz hangi anahtarların çıkarılmaya iyi aday olduğunu tahmin edip onlara kısa süre verebiliyorsa. Anahtar sürelerini iyi kullanıyorsanız, anahtarlar çoğu zaman çıkarılmadan önce süresi dolarak silindiği için bellek sınırına daha az takılırsınız.
volatile-lru, volatile-lrm ve volatile-random politikaları esas olarak tek bir Redis örneğini hem önbellek hem de bir grup kalıcı anahtar için kullanmak istediğinizde işe yarar. Ancak belge, mümkünse böyle bir durumda iki ayrı Redis örneği çalıştırmayı düşünmenizi önerir. Bir başka nokta da şudur: bir anahtara süre atamak bellek harcar; bu yüzden allkeys-lru, çalışmak için süreye ihtiyaç duymadığından bellek açısından daha verimlidir.
INFO ile politikanın işe yarayıp yaramadığını ölçmek
INFO stats bölümündeki iki alan önbellek başarımı için temel ölçüdür: keyspace_hits (anahtarın bulunduğu aramalar) ve keyspace_misses (istenip bulunamayan anahtarlar). Önbellekten karşılanan erişimlerin yüzdesi şöyle hesaplanır:
keyspace_hits / (keyspace_hits + keyspace_misses) * 100Belgeye göre EXISTS komutunun anahtarın olmadığını bildirmesi de bir ıska olarak sayılır; varlık kontrolünü sık yapan uygulamalarda oran bu yüzden düşük görünebilir. İsabet oranı beklediğinizden düşükse belge şu akıl yürütmeyi önerir. Küçük bir "sıcak" veri alt kümesinin erişimlerin yaklaşık yüzde 75'ini oluşturmasını bekliyorsanız isabet oranının da yüzde 75 civarında olmasını beklersiniz. Oran daha düşükse evicted_keys değerine bakın: yüksek bir çıkarma oranı, politikanın yanlış anahtarları çok sık sildiğini düşündürür ve allkeys-lru iyi bir seçenek olabilir. evicted_keys düşük ve anahtar süreleri kullanıyorsanız expired_keys değerine bakın; bu değer yüksekse süreler çok kısa olabilir ya da yanlış anahtarlara süre veriyor olabilirsiniz.
| INFO alanı | Bölüm | Ne söyler |
|---|---|---|
| keyspace_hits, keyspace_misses | stats | İsabet ve ıska sayıları |
| evicted_keys | stats | maxmemory yüzünden çıkarılan anahtar sayısı |
| expired_keys | stats | Süresi dolarak silinen anahtar olayları |
| used_memory_dataset | memory | Veri için kullanılan bellek; maxmemory üzerindeyse fark aşım miktarıdır |
| current_eviction_exceeded_time | stats | Kullanımın en son maxmemory üzerine çıkmasından beri geçen süre, ms |
| total_eviction_exceeded_time | stats | Başlangıçtan beri kullanımın maxmemory üzerinde kaldığı toplam süre, ms |
| mem_not_counted_for_evict | memory | Eviction hesabına girmeyen tampon belleği |
| maxmemory_policy | memory | Geçerli politika |
commandstats bölümü de her komutun kaç kez reddedildiğini raporlar. noeviction ya da volatile- politikalarından birini kullanıyorsanız, hangi komutların bellek sınırı yüzünden durdurulduğunu ve bunun ne sıklıkta olduğunu buradan bulabilirsiniz. Politikayı değiştirdikten sonra temiz bir ölçüm için sayaçları CONFIG RESETSTAT ile sıfırlayabilirsiniz. INFO bölümlerinin tamamı INFO komutu yazısında.
Yaklaşık LRU algoritması
Redis'in LRU algoritması en az kullanılan anahtarları tam olarak hesaplamaz, yaklaşık olarak bulur: rastgele küçük bir anahtar örneği alır ve bunlar arasından son erişimin üzerinden en uzun süre geçmiş olanları çıkarır. Redis 3.0'dan beri algoritma iyi adaylardan oluşan bir havuz da tutar; bu, sonucu gerçek LRU'ya yaklaştırır. Gerçek LRU kullanılmamasının nedeni daha fazla bellek gerektirmesidir; belge, yaklaşımın Redis kullanan bir uygulama için neredeyse eşdeğer olduğunu söyler.
Algoritmanın doğruluğu, her çıkarmadan önce kaç anahtarın örnekleneceğini belirleyen maxmemory-samples ayarıyla ayarlanır:
maxmemory-samples 5Belgedeki karşılaştırmaya göre Redis 3.0, 5 örnekle Redis 2.8'den daha iyi sonuç verir; 10 örnekle yaklaşım teorik performansa çok yaklaşır. Örnek sayısını 10'a çıkarmak biraz daha fazla CPU harcar; bunun ıska oranınızda fark yaratıp yaratmadığını ölçmeniz önerilir. Değeri üretimde denemek CONFIG SET maxmemory-samples <sayı> ile kolaydır. Belge ayrıca erişim deseniniz kuvvet yasasına (power law) benziyorsa, simülasyonlarda gerçek LRU ile Redis yaklaşımı arasındaki farkın çok küçük ya da hiç olmadığını belirtir.
LFU: erişim sıklığına göre çıkarma

Redis 4.0 ile gelen LFU modu bazı durumlarda daha iyi isabet oranı verebilir. Bu modda Redis anahtarlara erişim sıklığını izler; seyrek kullanılanlar çıkarılır, sık kullanılanların bellekte kalma olasılığı artar. İki politika vardır: volatile-lfu süresi olan anahtarlar arasından, allkeys-lfu tüm anahtarlar arasından seçer.
LFU da LRU gibi yaklaşıktır. Erişim sıklığı, nesne başına yalnızca birkaç bit kullanan olasılıksal bir sayaçla (Morris sayacı) tahmin edilir ve zamanla azaltılır; böylece geçmişte sık erişilmiş ama artık kullanılmayan anahtarlar zamanla "sıcak" sayılmaktan çıkar ve algoritma erişim desenindeki değişime uyum sağlar. Varsayılan olarak sayaç yaklaşık bir milyon istekte doygunluğa ulaşır ve her dakika azaltılır. Ayarlar şunlardır:
lfu-log-factor 10
lfu-decay-time 1lfu-decay-time dakika cinsindendir: örneklendiğinde bu değerden eski bulunan sayaç azaltılır; 0 sayacın hiç azaltılmayacağı anlamına gelir. lfu-log-factor ise 0 ile 255 arasındaki sayacı doyurmak için kaç erişim gerektiğini değiştirir. Faktör büyüdükçe en yüksek değere ulaşmak için daha çok erişim gerekir; küçüldükçe az erişilen anahtarlar arasında ayrım çözünürlüğü artar. Belgedeki tablo bu dengeyi gösterir:
| Faktör | 100 erişim | 1000 erişim | 100K erişim | 1M erişim | 10M erişim |
|---|---|---|---|---|---|
| 0 | 104 | 255 | 255 | 255 | 255 |
| 1 | 18 | 49 | 255 | 255 | 255 |
| 10 | 10 | 18 | 142 | 255 | 255 |
| 100 | 8 | 11 | 49 | 143 | 255 |
Bir anahtarın LFU sayacını OBJECT FREQ anahtar ile okuyabilirsiniz; bu komut yalnızca maxmemory-policy bir LFU politikasıyken kullanılabilir. Tersine, son erişimden beri geçen saniyeyi döndüren OBJECT IDLETIME yalnızca politika LFU değilken kullanılabilir. Her iki komut da anahtar yoksa nil döndürür. Diğer OBJECT ve MEMORY komutları bellek kullanımı yazısında.
LRM: son değişikliğe göre çıkarma (Redis 8.6)
Redis 8.6 ile gelen LRM (Least Recently Modified) politikası LRU'ya benzer, ancak zaman damgasını yalnızca yazma işlemlerinde günceller; okumalar damgayı değiştirmez. LRU ise hem okuma hem yazmada günceller. Bu fark LRM'yi, ne sıklıkla okunduğundan bağımsız olarak uzun süredir güncellenmemiş eski veriyi çıkarmak istediğiniz durumlarda kullanışlı kılar: örneğin okuma ve yazma iş yüklerinin net biçimde ayrıldığı uygulamalar. volatile-lrm süresi olan anahtarlar, allkeys-lrm tüm anahtarlar arasından seçer. LRM de örnekleme kullanan yaklaşık bir algoritmadır ve maxmemory-samples ayarı ona da uygulanır. Bu politikalar 8.6 öncesi sunucularda yoktur.
OOM hatası
Bellek sınırına ulaşan ve komut için yer açamayan Redis şu hatayı döndürür; veri ekleyen komutlar başarısız olur, okuma ve silme komutları çalışmaya devam eder:
> SET newkey "value"
(error) OOM command not allowed when used memory > 'maxmemory'.
> GET oldkey
"value"OOM hata sayfası teşhis için INFO memory çıktısında used_memory_human ile maxmemory_human değerlerini karşılaştırmayı ve maxmemory_policy değerine bakmayı önerir. Çözüm seçenekleri: Redis önbellek olarak kullanılıyorsa allkeys-lru gibi bir çıkarma politikası seçmek, volatile- politikalarında anahtarlara süre vermek, makinede yeterli bellek varsa maxmemory değerini yükseltmek ya da artık gerekmeyen anahtarları silmek. Lua fonksiyonları ve #!lua satırıyla başlayan betikler, allow-oom ya da no-writes bayrağı yoksa daha başlamadan aynı hatayı alır; bu bayraklar Lua script yazısında. OOM ile birlikte sık görülen diğer sunucu hataları OOM, MISCONF ve READONLY yazısında.
Bu mekanizma, istemci bağlantılarının toplam belleğini sınırlayan maxmemory-clients ayarından farklıdır; o ayar anahtar değil bağlantı keser ve CLIENT LIST ve bağlantı yönetimi yazısında anlatılıyor.
Kapasite denemek için redis-cli --lru-test
redis-cli'nin özel bir modu, isteklerin yüzde 20'lik anahtar kümesine yüzde 80 oranında yöneldiği (80-20) bir dağılımla GET ve SET simülasyonu yapar ve her saniye isabet ile ıska oranlarını yazar. Belge, gerçekçi bir sonuç için maxmemory ve uygun bir politikanın (çoğu zaman allkeys-lru) ayarlanmasının şart olduğunu vurgular. Belgedeki örnekte 10 milyon anahtar ve 100 MB sınırla ıska oranı yüzde 59 civarında dengelenir; yarım gigabaytla bu oran yüzde 3 civarına düşer.
./redis-cli --lru-test 10000000Sık Sorulan Sorular
Redis'in varsayılan maxmemory-policy değeri nedir?
OOM hata sayfasına göre varsayılan politika noeviction değeridir. Bu politikada Redis sınıra ulaşınca anahtar silmez, yeni veri ekleyen komutlara OOM hatası döndürür.
volatile-lru seçtim ama yine OOM alıyorum, neden?
volatile- politikaları yalnızca süresi olan anahtarlardan seçer. Hiçbir anahtarın süresi yoksa ya da süreli anahtarlar yer açmaya yetmiyorsa politika noeviction gibi davranır. Anahtarlara süre verin ya da allkeys- politikalarından birine geçin.
maxmemory değerini makinenin tüm RAM'ine eşitlemeli miyim?
Replikasyon ya da kalıcılık kullanıyorsanız hayır. Bu tamponların belleği maxmemory hesabına girmez; belge tamponlar için biraz RAM bırakmanızı ve mem_not_counted_for_evict değerini tahmin için kullanmanızı önerir.
LRU mu LFU mu?
Belge, başka bir nedeniniz yoksa allkeys-lru politikasını iyi bir varsayılan olarak önerir. LFU bazı durumlarda daha iyi isabet oranı verebilir; karar için politikayı değiştirip keyspace_hits ve keyspace_misses oranını ölçün.
maxmemory-samples değerini artırmak ne kazandırır?
Daha fazla anahtar örneklendiği için çıkarma kararı gerçek LRU'ya yaklaşır, ancak biraz daha CPU harcanır. Belgeye göre 10 örnek teorik performansa çok yakındı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 · Redis bellek kullanımı ve MEMORY USAGE · EXPIRE ve TTL · Önbellek nedir · OOM, MISCONF ve READONLY hataları