Eksiksiz Redis Rehberi — Özellikler, En İyi Uygulamalar ve Tasarım Kalıpları
Redis veri yapıları, mimarisi, operasyonel kalıpları ve production best practice’leri için kapsamlı bir başvuru kaynağı.
İçindekiler
- Giriş ve Temel Kavramlar
- Veri Tiplerine Derinlemesine Bakış
- TTL (Süre Sonu) ve Eviction (Tahliye)
- Kalıcılık: RDB & AOF
- Replication (Çoğaltma)
- Redis Sentinel (Yüksek Erişilebilirlik)
- Redis Cluster (Sharding)
- Transaction’lar ve Scripting
- Pub/Sub & Streams
- Yaygın Tasarım Kalıpları
- Cache (Önbellekleme) Stratejileri
- Performans ve Bellek Optimizasyonu
- Güvenlik En İyi Uygulamaları
- İzleme ve Gözlemlenebilirlik
- Kaçınılması Gereken Anti-Pattern’ler
- Client Kütüphaneleri ve Connection Pooling
- Yedekleme, Felaket Kurtarma ve Upgrade
1. Giriş ve Temel Kavramlar
Redis (REmote DIctionary Server), bellek-içi (in-memory) bir veri yapısı deposu olup; veritabanı, cache, mesaj kuyruğu ve stream motoru olarak kullanılabilir. Her mühendisin içselleştirmesi gereken temel mimari gerçekler:
- Tek thread’li komut işleme modeli (Redis 6’dan itibaren ağ okuma/yazma için I/O thread’leri var, ancak komutların bizzat çalıştırılması hâlâ tek thread’lidir). Bu, Redis komutlarının birbirine göre atomik olduğu anlamına gelir — aynı instance üzerinde iki komut asla paralel çalışmaz.
- Öncelikle bellek-içi (in-memory): aktif veri RAM’de tutulur; diske kalıcılık isteğe bağlıdır ve varsayılan olarak asenkrondur.
- Zengin veri tipleri — sadece key-value string değil. Redis’i Memcached’den ayıran temel fark budur.
- Son derece düşük gecikme (latency): çoğu işlem için milisaniye altı, çünkü kritik yolda disk I/O yoktur.
Tek thread’li olmak neden önemli?
Aynı anda sadece bir komut çalıştığı için:
- Uzun süren komutlar (örn.
KEYS *, sınırsızSORT, çok büyükSMEMBERS) health check dahil her şeyi bloklar — bu production kesintilerinin başlıca sebeplerinden biridir. - Tek bir Redis operasyonu için application-side (uygulama tarafı) locking’e gerek yoktur, fakat çok adımlı “oku-değiştir-yaz” mantığı kurarken dikkatli olunmalıdır (bkz. Transaction’lar bölümü).
2. Veri Tiplerine Derinlemesine Bakış
String
En temel tip; metin, serialize edilmiş JSON veya 512MB’a kadar binary veri tutabilir.
SET user:1000:name "Ayşe"
GET user:1000:name
INCR page:views # atomik sayaç
INCRBY wallet:1000 500
SETEX session:abc123 3600 "token-data" # tek çağrıda TTL
SETNX lock:job:42 "worker-1" # sadece yoksa set et (naif locking)
En iyi uygulama: Ayrı SETNX + EXPIRE yerine SET key value EX seconds NX kullanın — birleşik form atomiktir; iki ayrı çağrı yaparsanız race condition penceresi oluşur.
SET lock:job:42 "worker-1" EX 30 NX
Hash
Birden fazla key kullanmaya gerek kalmadan bir nesneyi (satır/döküman gibi) temsil etmek için idealdir.
HSET user:1000 name "Ayşe" email "[email protected]" age 29
HGET user:1000 name
HGETALL user:1000
HINCRBY user:1000 login_count 1
HDEL user:1000 age
En iyi uygulama: Küçük nesneler için birçok düz string key (user:1000:name, user:1000:email, …) yerine varlık başına tek bir hash kullanın. Hash’ler, dahili listpack encoding sayesinde küçük nesneler için çok daha bellek-verimlidir ve tüm varlığı atomik olarak okuyup güncellemenizi sağlar.
List
Sıralı koleksiyon, quicklist node’larından oluşan bağlı liste olarak implemente edilmiştir. Kuyruklar, zaman çizelgeleri, son aktivite akışları için harikadır.
LPUSH queue:jobs "job1"
RPUSH queue:jobs "job2"
LPOP queue:jobs
BRPOP queue:jobs 5 # 5sn timeout'lu bloklayan pop — basit iş kuyruklarının temeli
LRANGE timeline:user:1000 0 20 # son 20 öğe
LTRIM timeline:user:1000 0 999 # liste boyutunu sınırla (sadece son 1000'i tut)
En iyi uygulama: Sınırsız bellek büyümesini önlemek için sınırlı listeleri (örn. aktivite akışları) her zaman LTRIM ile kırpın.
Set
Sırasız, benzersiz koleksiyon. Etiketler, benzersiz ziyaretçi takibi, ilişki grafikleri için mükemmeldir.
SADD tags:post:55 "redis" "database" "cache"
SISMEMBER tags:post:55 "redis"
SINTER online:users vip:users # kesişim: online VIP kullanıcılar
SUNIONSTORE all:tags tags:post:55 tags:post:56
SCARD tags:post:55 # eleman sayısı
Sorted Set (ZSet)
Kayan noktalı bir skora göre sıralanmış benzersiz elemanlar. Redis’in en güçlü yapılarından biri — leaderboard’ları (skor tabloları), rate limiter’ları, öncelik kuyruklarını, gecikmeli iş zamanlamasını destekler.
ZADD leaderboard 1500 "player1" 2200 "player2"
ZINCRBY leaderboard 50 "player1"
ZREVRANGE leaderboard 0 9 WITHSCORES # ilk 10
ZRANK leaderboard "player1"
ZRANGEBYSCORE leaderboard 1000 2000
ZREMRANGEBYRANK leaderboard 0 -1001 # ilk 1000'i tut, gerisini kırp
Kalıp — zaman sıralı olaylar: skor olarak timestamp kullanarak doğal sıralı bir olay günlüğü elde edin, ardından zaman aralığı sorguları için ZRANGEBYSCORE kullanın.
Bitmap
Bit dizisi olarak ele alınan string’ler — ölçekte boolean flag’ler için (örn. günlük aktif kullanıcı takibi) son derece bellek-verimlidir.
SETBIT active:2026-08-17 1000 1 # kullanıcı 1000 bugün aktifti
BITCOUNT active:2026-08-17 # günlük aktif kullanıcı sayısı
BITOP AND result active:mon active:tue # her iki gün de aktif olanlar
HyperLogLog
Yaklaşık kardinalite (benzersiz sayım) için olasılıksal bir yapı; küme boyutundan bağımsız olarak sadece ~12KB kullanır, ~%0.81 standart hata payıyla.
PFADD unique:visitors:2026-08-17 "user1" "user2" "user3"
PFCOUNT unique:visitors:2026-08-17
PFMERGE unique:visitors:month unique:visitors:2026-08-17 unique:visitors:2026-08-18
Ne zaman kullanılır: Devasa ölçekte yaklaşık benzersiz sayımlara (sayfa görüntüleme, benzersiz arama terimi) ihtiyaç duyup tam bir Set’in bellek maliyetini karşılayamıyorsanız.
Geospatial (Coğrafi Konum)
Dahili olarak sorted set üzerine kurulmuştur; enlem/boylam saklar ve yarıçap/kutu sorgularını destekler.
GEOADD shops -0.1276 51.5072 "shop:london"
GEOSEARCH shops FROMLONLAT -0.12 51.50 BYRADIUS 5 km ASC
GEODIST shops shop:london shop:paris km
Streams
Kafka tarzı günlüklere benzer, sadece-ekleme (append-only) log veri tipi (Redis 5’ten beri) — event sourcing, aktivite günlükleri ve çok-tüketicili pipeline’lar için doğru seçim (Bölüm 9’da daha detaylı).
XADD events:orders '*' order_id 1001 status "created"
XRANGE events:orders - +
XREAD COUNT 10 STREAMS events:orders 0
3. TTL (Süre Sonu) ve Eviction (Tahliye)
TTL Mekaniği
EXPIRE session:abc 3600
PEXPIRE session:abc 3600000 # milisaniye cinsinden
TTL session:abc # kalan saniye, -1 = TTL yok, -2 = key mevcut değil
PERSIST session:abc # TTL'yi kaldır
Redis, süresi dolmuş key’ler için iki mekanizma kullanır:
- Pasif: key erişildiğinde tembel (lazy) şekilde kontrol edilir.
- Aktif: arka planda çalışan bir döngü, TTL’li key’leri rastgele örnekleyerek süresi dolmuş olanları siler — bu, bir daha hiç erişilmese bile eski verinin tuttuğu belleği periyodik olarak sınırlar.
Eviction (Tahliye) Politikaları (maxmemory limitine ulaşıldığında)
| Politika | Davranış |
|---|---|
noeviction | Bellek dolduğunda yazma işlemlerinde hata döner (varsayılan) |
allkeys-lru | Tüm key’ler arasında en az kullanılanı (LRU) tahliye eder |
volatile-lru | TTL’si olan key’ler arasında LRU tahliye eder |
allkeys-lfu | En az sıklıkla kullanılan key’i tahliye eder (dengesiz erişim örüntüleri için daha iyi) |
volatile-lfu | TTL’li key’ler arasında LFU |
allkeys-random | Rastgele tahliye |
volatile-random | TTL’li key’ler arasında rastgele tahliye |
volatile-ttl | Kalan TTL’si en kısa olan key’leri önce tahliye eder |
En iyi uygulama: Redis salt cache olarak kullanılıyorsa allkeys-lru veya allkeys-lfu kullanın. Cache ve kalıcı veri (örn. session + kalıcı sayaçlar) aynı instance’ta karışıksa volatile-lru/volatile-lfu kullanın ve kalıcı key’lere asla TTL vermeyin — ancak mümkünse cache ve ana veri deposu iş yüklerini farklı instance’lara ayırmayı ciddi olarak düşünün.
4. Kalıcılık: RDB & AOF
RDB (Redis Database Snapshot)
SAVE (bloklayan) veya BGSAVE (child process fork eder, bloklamaz) ile tetiklenen zaman noktası binary anlık görüntüsü.
save 900 1 # 900sn içinde >=1 yazma varsa snapshot al
save 300 10
save 60 10000
- Artıları: kompakt tek dosya, hızlı yeniden başlatma, yedekleme için iyi.
- Eksileri: snapshot’lar arasında veri kaybı penceresi vardır; çok büyük veri setlerinde
fork()gecikme sıçramalarına neden olabilir (copy-on-write bellek baskısı).
AOF (Append Only File)
Her yazma operasyonunu loglar; yeniden başlatmada tekrar oynatılır.
appendonly yes
appendfsync everysec # her saniye fsync (en iyi denge)
# appendfsync always # her yazmada fsync — en güvenli, en yavaş
# appendfsync no # işletim sistemine bırak — en hızlı, en az güvenli
Redis 7’den itibaren AOF, çok parçalı format (base dosya + incremental dosyalar + manifest) kullanır; bu, rewrite işlemlerini daha güvenli hale getirir ve eski tek-dev-dosya rewrite riskini ortadan kaldırır.
- Artıları: çok daha küçük veri kaybı penceresi (
everysecile ≤1sn), insan tarafından denetlenebilir log. - Eksileri: RDB’ye göre daha büyük dosya boyutu, potansiyel olarak daha yavaş yeniden başlatma (tüm log’u tekrar oynatma) — ancak
AOF rewriteperiyodik olarak sıkıştırır.
Önerilen production kurulumu
RDB + AOF’u birlikte kullanın: hızlı, kompakt yedekleme/geri yükleme için RDB; minimum veri kaybı için AOF. Redis, etkinleştirilmişse yeniden başlatmada AOF’u kullanır (daha eksiksizdir), aksi halde RDB’ye döner.
appendonly yes
appendfsync everysec
save 3600 1
save 300 100
save 60 10000
En iyi uygulama: Geri yükleme prosedürünüzü her zaman test edin — hiç geri yüklenmemiş bir yedek, yedek sayılmaz.
5. Replication (Çoğaltma)
Redis replication’ı asenkron, leader-follower (primary-replica) modelidir. Bir replica bağlanır, ilk tam senkronizasyonu yapar (RDB transferi), ardından sürekli bir komut akışı almaya başlar.
# Replica üzerinde:
replicaof 10.0.0.1 6379
# veya dinamik olarak:
REPLICAOF 10.0.0.1 6379
REPLICAOF NO ONE # primary'ye terfi ettir
Önemli gerçekler:
- Replication varsayılan olarak asenkrondur — bir yazma, tüm replica’lara ulaşmadan önce client’a onaylanabilir. Bir yazmayı “güvenli” saymadan önce daha güçlü dayanıklılık garantisi istiyorsanız
WAIT numreplicas timeoutkullanın. - Replica’lar varsayılan olarak salt okunurdur (
replica-read-only yes) — bu iyi bir uygulamadır, gelişigüzel devre dışı bırakmayın. - Zincirleme replication (replica’nın replica’sı) desteklenir; fan-out sırasında primary üzerindeki yükü azaltmak için kullanılabilir.
En iyi uygulama: Asenkron replication’ı asla dayanıklılığın (AOF/RDB) yerine geçen bir şey olarak görmeyin — node arızasına karşı korur, replication tamamlanmadan önce çökme durumunda veri kaybına karşı korumaz.
6. Redis Sentinel (Yüksek Erişilebilirlik)
Sentinel, sharding olmadan bir primary-replica kurulumu için otomatik failover, izleme ve servis keşfi sağlar.
sentinel monitor mymaster 10.0.0.1 6379 2 # quorum = en az 2 sentinel'in hemfikir olması gerekir
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
- Quorum tabanlı kararlar için (tek bir Sentinel’in yanlış pozitifinden kaynaklanan split-brain’i önlemek amacıyla) ayrı host’larda en az 3 Sentinel süreci çalıştırın.
- Uygulamalar, sabit kodlanmış bir IP yerine, güncel primary’yi dinamik olarak keşfeden Sentinel-farkında bir client üzerinden bağlanmalıdır.
- Sentinel, failover orkestrasyonunu yönetir; veriyi sharding yapmaz — bunun için Redis Cluster kullanın.
7. Redis Cluster (Sharding)
Redis Cluster, veriyi 16384 hash slot kullanarak birden fazla primary node arasında bölümlere ayırır. Her key, CRC16(key) mod 16384 ile bir slota eşlenir.
redis-cli --cluster create \
10.0.0.1:6379 10.0.0.2:6379 10.0.0.3:6379 \
10.0.0.4:6379 10.0.0.5:6379 10.0.0.6:6379 \
--cluster-replicas 1
Çoklu Key İşlemleri için Hash Tag’leri
Çoklu-key komutları (MGET, transaction’lar, Lua script’leri), tüm key’lerin aynı slotta bulunmasını gerektirir. {} hash tag’leri kullanarak birlikte konumlandırmayı zorlayın:
user:{1000}:profile
user:{1000}:settings
user:{1000}:sessions
Üçü de aynı slota hash’lenir çünkü sadece {} içindeki alt dizge hash’lenir.
- Cluster, otomatik failover ile node arızasına toleranslıdır (her primary’nin ≥1 replica’sı olmalıdır).
- Client, cluster yönlendirmesini (
MOVED/ASKyanıtları) desteklemelidir — düz tek-node client değil, cluster-farkında bir client kütüphanesi kullanın. - Hash tag kullanılmadıkça, slot’lar arası çoklu-key işlemleri hata verir (
CROSSSLOT).
En iyi uygulama: İleride Cluster’a geçmeyi öngörüyorsanız key şemanızı ilk günden hash tag’leriyle tasarlayın — hash tag’leri mevcut büyük bir veri setine sonradan eklemek çok zahmetlidir.
8. Transaction’lar ve Scripting
MULTI/EXEC
Komutları kuyruğa alır ve tek bir batch olarak atomik şekilde çalıştırır (SQL transaction’ları gibi gerçek “hata durumunda rollback” değildir — bir komuttaki runtime hatası diğerlerini durdurmaz).
MULTI
INCR counter
LPUSH log "event"
EXEC
WATCH (Optimistic Locking)
Compare-and-swap tarzı mantık için kullanılır (oku, hesapla, koşullu yaz).
WATCH balance:user:1000
val = GET balance:user:1000
# ... uygulamada yeni değeri hesapla ...
MULTI
SET balance:user:1000 newVal
EXEC # WATCH'tan sonra balance:user:1000 değiştiyse nil döner — retry mantığı gerekir
Lua Scripting (EVAL) ve Functions
Script’ler atomik olarak çalışır (tüm script tek, bölünmez bir birim olarak çalışır ve diğer komutları bloklar).
EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 mykey myvalue
Redis 7’den itibaren, Redis Functions (FUNCTION LOAD) geçici (ad-hoc) EVAL script’lerinin yerini alan önerilen yöntemdir — sadece script cache’inde tutulan script’lerin aksine, versiyonlanır, isimlendirilir ve replication/AOF üzerinde düzgün şekilde kalıcı hale getirilir.
En iyi uygulama: Lua script’lerini kısa tutun. Yavaş bir script, tıpkı yavaş bir komut gibi tüm sunucuyu bloklar — çalışan bir script’i güvenli şekilde kesintiye uğratan bir timeout mekanizması yoktur (admin SCRIPT KILL müdahalesi hariç; bu da yazma yapan script’leri güvenle kesemez).
9. Pub/Sub & Streams
Pub/Sub
Gönder-ve-unut (fire-and-forget) mesajlaşma. Kalıcılık yok, teslimat garantisi yok — dinleyen bir subscriber yoksa mesaj kaybolur.
SUBSCRIBE news:tech
PUBLISH news:tech "Redis 8 released"
PSUBSCRIBE news:* # pattern abonelik
Kullanım alanları: gerçek zamanlı bildirimler, cache-invalidation yayını, canlı dashboard’lar — dayanıklılık gerektiren hiçbir şey için kullanmayın.
Streams (kalıcı alternatif)
Streams, Pub/Sub’ın dayanıklılık açığını sadece-ekleme günlüğü, consumer group’lar ve onaylama (acknowledgment) ile çözer.
XADD orders:stream '*' order_id 123 status "paid"
# Consumer group kurulumu
XGROUP CREATE orders:stream processors '$' MKSTREAM
XREADGROUP GROUP processors worker-1 COUNT 10 STREAMS orders:stream '>'
XACK orders:stream processors 1234567-0
XPENDING orders:stream processors # onaylanmamış mesajları incele
XCLAIM orders:stream processors worker-2 60000 1234567-0 # takılı kalmış mesajı yeniden ata
En iyi uygulama: Sınırsız büyümeyi önlemek için stream boyutunu sınırlayın:
XADD orders:stream MAXLEN ~ 100000 '*' order_id 123
~ işareti kırpmayı yaklaşık (approximate) yapar (daha verimlidir, her eklemede tam kırpmayı önler).
10. Yaygın Tasarım Kalıpları
Dağıtık Lock (Redlock tarzı, basitleştirilmiş tek-instance)
SET lock:resource:42 "unique-random-token" NX EX 10
# ... kritik bölüm ...
# Sadece hâlâ sahibiyseniz serbest bırakın (başkasının lock'unu silmeyin):
EVAL "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end" 1 lock:resource:42 "unique-random-token"
Çoklu-instance güvenliği için Redlock algoritması, lock’u bağımsız Redis node’larının çoğunluğu üzerinde alır. Not: Redlock’un ağ bölünmeleri (network partition) altındaki doğruluğu tartışmalıdır (bkz. Martin Kleppmann’ın eleştirisi) — kritik güvenlik garantileri gerektiren senaryolarda, lock için Redis yerine konsensüs tabanlı bir servis (örn. Zookeeper, etcd) tercih edin.
Rate Limiting (Sorted Set ile Kayan Pencere)
ZADD ratelimit:user:1000 <timestamp> <unique-request-id>
ZREMRANGEBYSCORE ratelimit:user:1000 0 <timestamp - window>
ZCARD ratelimit:user:1000 # limitten büyükse reddet
EXPIRE ratelimit:user:1000 60
Rate Limiting (Basit Sabit Pencere)
INCR ratelimit:user:1000:minute:202608171530
EXPIRE ratelimit:user:1000:minute:202608171530 60
Leaderboard (Skor Tablosu)
ZADD leaderboard:game1 <score> <player_id>
ZREVRANGE leaderboard:game1 0 9 WITHSCORES
ZREVRANK leaderboard:game1 <player_id>
İş Kuyruğu (basit)
LPUSH queue:emails '{"to":"[email protected]","template":"welcome"}'
BRPOP queue:emails 0 # worker, iş gelene kadar bloklar
Güvenilirlik için (worker işlem sırasında çökerse işin kaybolmaması amacıyla), “processing” listesine BRPOPLPUSH/LMOVE kullanın, başarı durumunda kaldırın:
BLMOVE queue:emails queue:emails:processing 0 LEFT RIGHT
# başarı durumunda:
LREM queue:emails:processing 1 <job>
Retry, gecikmeli işler ve dead-letter yönetimi gerektiren production-grade kuyruklar için ham listeler yerine consumer group’lu Streams tercih edin.
Session Store
HSET session:abc123 user_id 1000 role "admin" ip "1.2.3.4"
EXPIRE session:abc123 1800
Cache (Cache-Aside)
1. Uygulama cache:key'i okur
2. Miss (bulunamazsa) → DB'den oku → SET cache:key value EX ttl
3. Hit (bulunursa) → cache'lenmiş değeri döndür
Idempotency (İdempotentlik) Key’leri
SET idempotency:req:abc123 "processed" NX EX 86400
# SET nil dönerse, istek zaten işlenmiş demektir — yeniden işlemeyi atlayın
Süresi Dolan Pencerelerle Sayaçlar (Analitik)
INCR pageviews:2026-08-17
EXPIRE pageviews:2026-08-17 2592000 # 30 gün tut
11. Cache (Önbellekleme) Stratejileri
| Strateji | Açıklama | Trade-off |
|---|---|---|
| Cache-Aside (Lazy Loading) | Uygulama önce cache’e bakar, miss durumunda DB’ye döner, cache’i doldurur | Basit, ancak tahliyeden sonraki ilk istek yavaştır; thundering herd riski var |
| Write-Through | Her yazma işlemi senkron olarak hem cache’e hem DB’ye gider | Cache her zaman güncel, ancak yazma gecikmesi artar |
| Write-Behind (Write-Back) | Cache’e hemen yaz, DB’ye asenkron flush et | Hızlı yazma, flush öncesi cache çökerse veri kaybı riski |
| Read-Through | Cache katmanının kendisi miss durumunda DB’den veri çeker (bir caching kütüphanesi aracılığıyla) | Daha temiz uygulama kodu, caching middleware gerektirir |
Thundering Herd / Cache Stampede’i Önleme
Popüler bir key’in süresi dolduğunda, birçok eşzamanlı istek aynı anda miss verip DB’ye yüklenebilir. Önlemler:
- Olasılıksal erken süre bitişi: gerçek TTL’den biraz önce, rastgele bir olasılıkla ağırlıklandırılarak yeniden hesaplama.
- Locking: miss veren ilk istek kısa bir lock alır ve yeniden hesaplar; diğerleri bekler veya bayat veri sunulur.
- Hiç süresi dolmasın + arka planda yenileme: arka plan işi veriyi yenilerken bayat veri sunmaya devam edin.
Cache Penetration’ı Önleme (var olmayan key’ler için sorgular)
Negatif sonuçları da cache’leyin (kısa TTL ile), veya DB’ye gitmeden önce kesinlikle var olmayan key sorgularını reddetmek için bir Bloom filter kullanın.
Cache Key Tasarımı
- Tutarlı, hiyerarşik isimlendirme kullanın:
<namespace>:<entity>:<id>:<field>örn.app:user:1000:profile. - Şema değişikliklerinde versiyonu artırarak anında cache invalidation yapabilmek için bir versiyon prefix’i ekleyin (
v2:user:1000).
12. Performans ve Bellek Optimizasyonu
Production’da Yavaş Komutlardan Kaçının
KEYS *— tüm key alanını tarar, bloklar. Bunun yerineSCANkullanın (cursor tabanlı, bloklamaz).
SCAN 0 MATCH user:* COUNT 100
FLUSHALL/FLUSHDB— açıkça yıkıcıdır, ayrıcaASYNCkullanılmadıkça büyük veri setlerinde bloklar:
FLUSHALL ASYNC
- Büyük koleksiyonlarda sınırsız
SORT,SMEMBERS,HGETALL,LRANGE 0 -1— bunun yerine sınırlı aralıklar/sayfalama ileSSCAN/HSCAN/LRANGEkullanın.
Pipelining
Ağ gecikmesi ek yükünü ortadan kaldırmak için birden fazla komutu tek round trip’te toplu gönderin:
redis-cli --pipe <<EOF
SET a 1
SET b 2
SET c 3
EOF
Client kodunda pipelining, binlerce round trip’i tek bir isteğe dönüştürebilir; toplu işlemler için genellikle 10-100x throughput iyileştirmesi sağlar.
Bellek Optimizasyonu
- Key başına bellek maliyetini incelemek için
MEMORY USAGE <key>kullanın. - Küçük nesneler için birçok string key yerine hash tercih edin (dahili
listpackencoding, ayarlanabilir eşiklerin altında kompakttır):
hash-max-listpack-entries 128
hash-max-listpack-value 64
- Aynı prensip küçük list, set ve sorted set’ler için de geçerlidir —
list-max-listpack-size,set-max-listpack-entries,zset-max-listpack-entriesdeğerlerini ayarlayın. - Ölçekte kısa key ve field isimleri kullanın — her byte milyonlarca key’de tekrarlanır.
- Redis’in beklediğiniz kompakt encoding’i kullandığını doğrulamak için
OBJECT ENCODING <key>kullanmayı düşünün.
Bağlantı ve Komut Verimliliği
- Tek tek
GET/SETdöngüsü yerineMGET/MSETkullanın. - Sık çalışan döngülerde
EXPIRE‘ı tutumlu kullanın; TTL’yi oluşturma anında bir kez ayarlamayı tercih edin. - Production’da
DEBUGkomutlarından veMONITOR‘dan kaçının — özellikleMONITOR, her komutu client’a stream ettiği için throughput’a ciddi zarar verir.
13. Güvenlik En İyi Uygulamaları
- Redis’i asla doğrudan internete açmayın. Sadece özel arayüzlere bind edin:
bind 127.0.0.1 10.0.0.5
protected-mode yes
- Kimlik doğrulama zorunlu kılın:
requirepass "cok-uzun-rastgele-bir-sifre"
- Tek bir paylaşılan şifre yerine ACL kullanın (Redis 6+) — kullanıcıları belirli komutlar ve key pattern’leriyle sınırlayın:
ACL SETUSER app-readonly on >password ~app:* +get +mget -@all
ACL SETUSER app-writer on >password ~app:* +@read +@write -flushall -flushdb -config
- Production’da tehlikeli komutları yeniden adlandırın veya devre dışı bırakın:
rename-command FLUSHALL ""
rename-command CONFIG "CONFIG_9f8a7b6c"
- Aktarım halindeki veri için TLS’i etkinleştirin (Redis 6+ native TLS destekler):
tls-port 6379
tls-cert-file /path/redis.crt
tls-key-file /path/redis.key
tls-ca-cert-file /path/ca.crt
- Ağ izolasyonu: Redis’i özel bir subnet/VPC’ye yerleştirin, security group/firewall ile erişimi kısıtlayın, tek savunma katmanı olarak asla sadece
requirepass‘a güvenmeyin. - Uyumluluk gereksinimi varsa, application-level şifreleme olmadan düz metin sırları değer olarak saklamaktan kaçının.
14. İzleme ve Gözlemlenebilirlik
İzlenmesi Gereken Temel Metrikler
INFO all
Şunlara dikkat edin:
used_memory/used_memory_rss/mem_fragmentation_ratio(ideal ~1.0–1.5; çok daha yüksekse fragmentasyon var demektir)connected_clientsinstantaneous_ops_per_seckeyspace_hits/keyspace_misses(hit oranı = hits / (hits+misses))evicted_keys— sıfırdan farklı ve artıyorsa bellek baskısı altındasınız demektirexpired_keysrejected_connectionsblocked_clientsmaster_repl_offset/ replication gecikmesi (replica’lardaINFO replication)latest_fork_usec— yüksek değerlerBGSAVE/BGREWRITEAOFfork gecikme etkisini gösterir
Yavaş Sorgu Günlüğü
CONFIG SET slowlog-log-slower-than 10000 # 10ms'den yavaş komutları logla (birim mikrosaniye)
SLOWLOG GET 25
SLOWLOG RESET
Gecikme (Latency) İzleme
CONFIG SET latency-monitor-threshold 100 # ms
LATENCY HISTORY command
LATENCY LATEST
Önerilen Araçlar
- Canlı gecikme örneklemesi için
redis-cli --latency/--latency-history. - Bloklama riski taşıyan ya da bellek dengesizliği yaratan aşırı büyük key’leri taramak için
redis-cli --bigkeys. - Zaman serisi metrikleri ve alerting için Prometheus +
redis_exporter. - Canlı güncellenen özet görünüm için
redis-cli --stat.
15. Kaçınılması Gereken Anti-Pattern’ler
- Uygulama kodunda
KEYS *kullanmak — her zamanSCANkullanın. - Tek bir key’de dev boyutlu değerler saklamak (çok-MB blob’lar) — o shard/slot için performansı düşürür, replication’ı zorlaştırır; parçalama (chunking) veya sadece pointer tutan harici obje depolamayı düşünün.
- Cache key’lerinde TTL olmaması — sınırsız bellek büyümesine ve bayat veriye yol açar.
- Her şey için tek bir dev Redis instance’ı (cache + kuyruk + session + pub/sub) — bir iş yükündeki yavaş komut veya tahliye fırtınası, ilgisiz iş yüklerini de bozar; mümkün olduğunda kullanım alanına göre izole edin.
maxmemory-policy‘yi göz ardı etmek — salt-cache bir instance’tanoevictionolarak bırakmak, zarif tahliye yerine yazma hatalarına neden olur.- Replication’ı yedek (backup) sanmak — değildir; kötü bir
DEL/FLUSHALLanında tüm replica’lara replike olur. - Cluster’a ölçeklenmeden önce çoklu-key atomik işlemler gerektiren key’leri hash-tag’lememek.
- Client-side connection pool’lara health check yapmadan körü körüne güvenmek — failover sonrası eski (stale) bağlantılar sessiz hatalara neden olur.
- Debug için production’da
MONITORçalıştırmak — ciddi throughput kaybı. - “Redis diske kalıcılık sağlıyor” varsayımıyla, kaybetmeyi göze alamayacağınız veri için
appendfsync everysecveya eşdeğerini ayarlamamak. mem_fragmentation_ratio‘yu göz ardı etmek — zamanla fragmentasyon,used_memory‘nin gösterdiğinden çok daha fazla RSS tüketebilir; uzun ömürlü instance’lar içinactivedefrag yesdüşünün.- Redis’e senkron cross-region çağrılar yapmak — Redis’i her zaman uygulama katmanına yakın (aynı AZ/region) konumlandırın; cross-region round trip’ler bellek-içi bir deponun amacını boşa çıkarır.
16. Client Kütüphaneleri ve Connection Pooling
- Her zaman bir connection pool kullanın, her istek için yeni bir TCP bağlantısı asla açmayın.
- Popüler client’lar:
redis-py(Python),ioredis/node-redis(Node.js),Jedis/Lettuce(Java),go-redis(Go),StackExchange.Redis(.NET). - Cluster deployment’ları için, client’ınızın cluster-farkında varyantını kullanın (örn.
redis-py>=4‘e yerleşikredis-py-clusterdesteği,ioredisCluster modu,Lettucecluster client) — bunlarMOVED/ASKyönlendirmelerini ve slot cache’lemesini doğru şekilde yönetir. - Makul timeout’lar ayarlayın (
socket_timeout,connect_timeout) — timeout’suz asılı kalan bir Redis çağrısı, uygulama genelinde thread pool tükenmesine yol açabilir. - Client-side caching ve daha iyi push-message desteği gibi özellikler için RESP3 protokolünü (Redis 6+) destekleyen client’ları tercih edin.
17. Yedekleme, Felaket Kurtarma ve Upgrade
- Düzenli
BGSAVEsnapshot’ları zamanlayın ve RDB dosyalarını rotasyonla host dışına (S3, GCS vb.) taşıyın. - Geri yükleme prosedürlerini düzenli olarak production-dışı bir instance üzerinde test edin — test edilmemiş bir yedek risktir.
- Büyük versiyon upgrade’leri için her zaman önce bir replica üzerinde test edin, sürümün breaking-changes notlarını inceleyin ve önceki sürüme geri dönüş planıyla yayına alın.
- Cluster upgrade’leri için, önce-replica rolling upgrade kullanın: replica’ları güncelleyin, failover yapın, ardından eski primary’leri güncelleyin.
redis.confdosyasını versiyon kontrolünde tutun ve konfigürasyonu kod gibi ele alın — takip edilmeyen manuelCONFIG SETdeğişiklikleri, “yeniden başlatmadan önce çalışıyordu” tarzı olayların yaygın bir sebebidir (çünküCONFIG SET,CONFIG REWRITEile takip edilmedikçe sadece runtime’da geçerlidir).
Hızlı Başvuru: Komut Karmaşıklığı Referans Tablosu
| Komut | Karmaşıklık | Not |
|---|---|---|
GET/SET | O(1) | |
HGET/HSET | O(1) | |
LPUSH/RPUSH | O(1) | |
LRANGE | O(S+N) | S=başlangıç offset’i, N=döndürülen eleman sayısı — büyük N’den kaçının |
SADD/SISMEMBER | O(1) ort. | |
ZADD | O(log N) | |
ZRANGE | O(log N + M) | M=döndürülen eleman sayısı |
KEYS | O(N) | Production’da kaçının |
SCAN | Çağrı başına O(1) | Cursor tabanlı, production için güvenli |
SORT | O(N log N) | Büyük koleksiyonlarda maliyetli olabilir |
FLUSHALL | O(N) | ASYNC kullanın |
Bu rehber, Redis 7.x/8.x nesli itibarıyla Redis davranışını yansıtmaktadır. Varsayılanlar ve mevcut komutlar sürümler arasında değişebildiğinden, kullandığınız kesin sürüm için her zaman redis.io üzerindeki resmi dokümantasyonu çapraz kontrol edin.