Cache Olarak Redis vs Database Olarak Redis
Redis bir projeye genelde sessizce giriyor. Biri yavaş bir database query'sini cache'lemek için ekliyor, varsayılanlarla configure ediyor, ve devam ediyor. On sekiz ay sonra, aynı instance artık user session'larını, rate-limiting counter'larını, feature flag state'ini, ve bir iki queue'yu da tutuyor, bunların hiçbiri başka hiçbir yere önce yazılmamış. Instance değişmedi. Ona ne için güvenildiği değişti, ve configuration bunu hiç yakalamadı.
Cache modu: data'yı kaybetmek tasarım gereği sorun değil
Redis gerçekten bir cache olduğunda, içindeki her key, başka bir yerde var olan bir şeyin kopyası, ya da onu yeniden hesaplamanın maliyeti. Redis restart olursa ve cache boşsa, application yeniden dolana kadar biraz daha yavaş oluyor, ama hiçbir şey kaybolmuyor. Bu durum için doğru configuration tam olarak bunu kucaklıyor:
maxmemory 2gb
maxmemory-policy allkeys-lru
save ""
maxmemory-policy allkeys-lru, Redis memory limit'ine ulaştığında, yeni key'lere yer açmak için en uzun süre kullanılmamış key'leri evict ettiği anlamına geliyor, bir cache için tam olarak doğru davranış. save "", RDB snapshot'ını tamamen disable ediyor, burada her şey reconstruct edilebildiği için persist etmenin disk I/O'suna değecek hiçbir şey yok.
Database modu: data'yı kaybetmek gerçek bir incident
Redis, başka hiçbir source of truth'u olmayan bir şeyi, kaybedilirse her user'ı logout eden bir session'ı, henüz işlenmemiş job'ların bir queue'sunu, beklenmedik şekilde sıfırlanan bir counter'ı tutar tutmaz, hesap tamamen tersine dönüyor. Şimdi allkeys-lru aktif olarak tehlikeli: Redis, bir cache entry'sine yer açmak için bir session token'ını evict etmeye karar verebilir, ve bu bir performans aksaklığı değil, data loss. Configuration buna uymalı:
maxmemory-policy noeviction
appendonly yes
appendfsync everysec
noeviction, memory dolduğunda Redis'in sessizce bir şey silmek yerine write'larda bir error döndürmesi demek, ki bu sizi bir capacity problemini sessizce data kaybetmek yerine fark edip düzeltmeye zorluyor. appendonly yes, persistence için append-only file'ı enable ediyor, ve everysec, durability'yi write performansına karşı dengeliyor, bir crash'te son RDB snapshot'ından sonraki her şey yerine en fazla bir saniyelik write kaybediliyor.
Asıl tehlike, ikisini bilmeden karıştırmak
Riskli setup "cache" ya da "database" değil, ikisinin birden, aynı instance'da, ikisinden biri için seçilmiş bir configuration altında olması. Aynı keyspace'te cache entry'leri ve session token'larıyla allkeys-lru, Redis'in kaybedilmesi sorun olmayan bir cache entry'siyle olmayan bir session arasındaki farkı anlayamaması demek, en uzun süre kullanılmayanı evict ediyor, ki bu ikisinden biri olabilir. Bunun, load altında "user'lar rastgele logout oluyor" türünden, cache pressure'ın session key'lerini evict etmesine kadar izini sürmenin biraz zaman aldığı intermittent bir bug'a sebep olduğunu gördüm, çünkü semptomda Redis'in eviction policy'sine işaret eden hiçbir şey yoktu.
Ayırmak ayrı server'lar anlamına gelmek zorunda değil
Redis bir instance'da birden fazla logical database'i destekliyor (varsayılan olarak SELECT 0'dan SELECT 15'e), ama bunlar aynı maxmemory ve eviction policy'yi paylaşıyor, yani bunu gerçekten çözmüyor. Çözen şey, aynı host'ta bile olsa, her biri işine uygun configuration'a sahip iki Redis instance'ı çalıştırmak:
redis-server /etc/redis/cache.conf --port 6379
redis-server /etc/redis/store.conf --port 6380
Cache instance'ı allkeys-lru ve persistence yok alıyor. Store instance'ı noeviction ve AOF persistence alıyor, ve ideal olarak başka herhangi bir database gibi backup ediliyor, çünkü o noktada, o bir database.
Periyodik olarak sorulmaya değer soru
Bir süredir çalışan herhangi bir Redis instance'ı için: şu anda kaybolsa, sadece yavaşlamak değil, kalıcı olarak kaybolacak bir şey olur muydu? Cevap hayırsa, cache configuration'ı doğru ve değiştirecek bir şey yok. Cevap evetse, tek bir key pattern için bile olsa, bu artık, kimse bunu kasten karar vermiş olsun olmasın, bir database, ve bu soru zor yoldan cevaplanmadan önce onu da bir database gibi configure etmeye, monitor etmeye, ve backup etmeye değer.