İçeriğe geç
Muhammet Şafak
en
Güncelleme 1 dk okuma

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.

Shared Redis Kullanırken Namespace İzolasyonu — kapak görseli

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:

  1. Aramada netlik. redis-cli --scan --pattern 'prod:billing:*' ile sadece bir projenin anahtarlarını görebiliyorum.
  2. Yanlışlıkla silmeyi zorlaştırma. FLUSHDB yerine redis-cli --scan --pattern 'staging:*' | xargs redis-cli DEL yazarken 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:

  • SELECT komutu sadece o bağlantı için scope’lu — connection pool’da kaos.
  • Bazı kütüphaneler MULTI/EXEC blokları 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:

  1. Bir projenin trafiği diğerlerinin gecikmesini ölçülebilir biçimde etkiliyor.
  2. Bir proje persistent storage istiyor (RDB/AOF), diğerleri cache-only.
  3. 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.

Sık sorulanlar

3 soru

  • Uygulamaları neden Redis logical DB'leriyle ayırmıyoruz?

    Üç sebep. Seçili veritabanı bağlantının bir özelliğidir, bu da connection pool'da kaosa döner; bazı kütüphaneler MULTI/EXEC blokları içinde DB değiştirmeyi desteklemez; ve Redis Cluster yalnızca sıfırıncı veritabanını destekler, yani cluster'a geçtiğiniz gün kurduğunuz bütün varsayımlar çöker.

  • KEYS küçük bir instance için de tehlikeli mi?

    Tarama boyunca event loop'u bloke eder ve diğer bütün istemciler sırada bekler. 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 milisaniyelerdesiniz. Ama maliyet anahtar sayısıyla büyür ve milyonlarca anahtarlı instance'larda duraklama canınızı yakar. SCAN çağrı başına O(1); onu kullanın.

  • Paylaşılan instance'tan ne zaman vazgeçilir?

    Bir projenin trafiği diğerlerinin gecikmesini ölçülebilir biçimde etkilediğinde, bir proje persistent storage isterken diğerleri cache-only kaldığında ya da bir proje farklı bir Redis sürümüne veya özelliğine ihtiyaç duyduğunda. Bunlardan önce bir prefix yazmak, yeni bir process başlatmaktan ucuzdur.

Kaynaklar

İlgili

Yorumlar

Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi