Shared Redis Kullanırken Namespace İzolasyonu
Tek bir Redis instance birden çok proje arasında paylaşılırken key collision ve yanlışlıkla silme kazalarından korunmak için kullandığım örüntü.
Kısaca
Paylaşılan bir Redis'te izolasyonu logical DB'ler değil, anahtar şeması sağlar. env, app ve bounded-context'ten oluşan üç katmanlı prefix aramayı netleştirir ve yanlışlıkla silmeyi zorlaştırır; prefix'i bağlantıya gömünce geliştirici unutsa bile sistem kendini korur. Logical DB'ler aynı işi göremez: bağlantıya bağlı bir durumdurlar ve Redis Cluster'da yalnızca sıfırıncı veritabanı vardır.
VPS başına bir Redis çalıştırmak küçük-orta projelerde gayet makul bir karar. Sorun, birden çok uygulama aynı instance’ı paylaşmaya başladığında ortaya çıkıyor: bir projenin users anahtarı diğerinin users anahtarını eziyor, biri FLUSHALL çağırınca herkes çuvallıyor.
Çözüm yeni bir Redis kurmak değil; namespace disiplini.
Üç katmanlı bir anahtar şeması
Üretimde şu kalıbı kullanıyorum:
<env>:<app>:<bounded-context>:<key>
Örnek:
prod:billing:invoice:42
prod:auth:session:1c2f...
staging:notify:queue:retry
Bu üçlüye sahip olmak iki şeyi getiriyor:
- Aramada netlik.
redis-cli --scan --pattern 'prod:billing:*'ile sadece bir projenin anahtarlarını görebiliyorum. - Yanlışlıkla silmeyi zorlaştırma.
FLUSHDByerineredis-cli --scan --pattern 'staging:*' | xargs redis-cli DELyazarken iki kez düşünüyorum.
Logical DB’lere güvenmeyin
Redis’in 0-15 arası logical DB’leri var ama tek kelimeyle: kullanmayın. Üç sebep:
SELECTkomutu sadece o bağlantı için scope’lu — connection pool’da kaos.- Bazı kütüphaneler
MULTI/EXECblokları içinde DB switch’i desteklemiyor. - Redis Cluster logical DB’leri zaten desteklemiyor; yarın cluster’a geçerseniz tüm varsayımınız çöker.
Namespace prefix’i öğrenip uygulamak tek yöntemdir.
Connection-level izolasyon
Laravel kullanıyorsanız config/database.php içinde her uygulama için ayrı bir Redis bağlantısı tanımlayın ve prefix ile namespace’i bağlantıya gömün:
'redis' => [
'billing' => [
'host' => env('REDIS_HOST'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
'prefix' => 'prod:billing:',
],
'auth' => [
// ...
'prefix' => 'prod:auth:',
],
],
Artık Redis::connection('billing')->set('invoice:42', ...) çağrısı otomatik olarak prod:billing:invoice:42 yazıyor. Geliştirici yanlışlıkla namespace yazmayı unutursa bile sistem kendini koruyor.
Tehlikeli komutları kapatın
redis.conf içinde production’da şu komutları yeniden adlandırmak veya kapatmak iyi bir fikir:
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command KEYS ""
KEYS özellikle önemli — tarama boyunca event loop’u bloke ediyor ve diğer tüm istemciler sırada bekliyor. Redis’in kendi dokümantasyonu 1 milyon anahtarlı bir veritabanını giriş seviyesi bir dizüstünde yaklaşık 40 ms’de tarıyor, yani 100k key’li bir instance’da milisaniyeler mertebesindesiniz — ama maliyet anahtar sayısıyla birlikte büyüyor, milyonlarca anahtarlı instance’larda duraklama canınızı yakacak kadar uzuyor. Yerine SCAN kullanılması zorunlu olmalı.
Ne zaman bu kalıbı bırakırsınız?
Üç sinyalden biri varsa ayrı Redis instance’larına geçin:
- Bir projenin trafiği diğerlerinin gecikmesini ölçülebilir biçimde etkiliyor.
- Bir proje persistent storage istiyor (RDB/AOF), diğerleri cache-only.
- Bir proje farklı bir Redis sürüm/feature ihtiyacı duyuyor.
Bunlardan önce şu basit kuralı aklınızda tutun: bir prefix yazmak, yeni bir process başlatmaktan ucuzdur.