Redis Cluster Kurulumu ve Sharding Mantığı

Yıllarca tek bir Redis instance üzerinde çalışan uygulamalar bir noktada duvara toslar. Ya bellek dolmuştur, ya yazma hızı yetersiz kalmıştır ya da tek node’un çökmesi tüm sistemi felç etmiştir. Redis Cluster tam bu noktada devreye girer ve işleri başka bir boyuta taşır. Bu yazıda sıfırdan bir Redis Cluster kurumu yapacak, sharding mantığını anlayacak ve production ortamında karşılaşacağın gerçek senaryolara hazırlıklı olacaksın.

Redis Cluster Nedir ve Neden Gerekli?

Redis Cluster, veriyi birden fazla node’a dağıtarak hem yatay ölçekleme hem de yüksek erişilebilirlik sağlayan bir çözümdür. Tek bir Redis instance’ı ne kadar güçlü bir sunucuya kurulursa kurulsun, belirli bir noktadan sonra bottleneck oluşturur. Özellikle saniyede yüz binlerce işlem yapan sistemlerde bu sınırı çok hızlı görürsün.

Redis Cluster’ın temel özellikleri şunlardır:

  • Otomatik sharding: Veriler hash slot sistemiyle node’lara bölünür
  • Replikasyon: Her master node’un bir veya birden fazla replica’sı olabilir
  • Otomatik failover: Master çöktüğünde replica otomatik olarak master olur
  • Lineer ölçekleme: Node ekleyerek kapasiteyi artırabilirsin

Hash Slot Mantığı: Sharding Nasıl Çalışır?

Redis Cluster toplam 16384 hash slot kullanır. Her anahtar, CRC16 algoritmasıyla bir hash slot’a atanır. Formül şu şekildedir:

HASH_SLOT = CRC16(key) mod 16384

Örneğin 3 master node’luk bir cluster kurduğunda slot dağılımı genellikle şöyle olur:

  • Node 1: 0 – 5460 arası slotlar
  • Node 2: 5461 – 10922 arası slotlar
  • Node 3: 10923 – 16383 arası slotlar

Bir istemci SET user:1001 "Ahmet" komutunu çalıştırdığında, Redis önce user:1001 anahtarının CRC16 değerini hesaplar, 16384’e böler ve hangi slot’a düştüğüne bakar. O slot hangi node’daysa istek oraya yönlendirilir.

Hash tags konusu burada kritiktir. Eğer birden fazla anahtarın aynı slot’ta olmasını istiyorsan, anahtarın içinde {} kullanırsın. Örneğin {user:1001}.name ve {user:1001}.email anahtarları her zaman aynı slot’ta tutulur. Bu özellikle multi-key komutları kullanırken şarttır.

Ortam Hazırlığı

Bu yazıda 6 node’luk bir cluster kuracağız: 3 master, 3 replica. Gerçek üretim ortamında bu node’lar farklı fiziksel sunucularda olmalıdır. Test için tek sunucuda farklı portlarla da yapabilirsin.

Önce Redis’i tüm sunuculara kuralım. Ubuntu/Debian için:

sudo apt update
sudo apt install -y redis-server

# Versiyon kontrolü
redis-server --version
# Redis server v=7.0.x

# Servisi durdur, konfigürasyonu elle yapacağız
sudo systemctl stop redis-server
sudo systemctl disable redis-server

CentOS/RHEL için:

sudo dnf install -y epel-release
sudo dnf install -y redis

sudo systemctl stop redis
sudo systemctl disable redis

Redis Cluster Konfigürasyonu

Her node için ayrı bir konfigürasyon dosyası oluşturman gerekiyor. Tek sunucuda test yapıyorsan port bazlı dizin yapısı kullanabilirsin:

# Dizin yapısını oluştur
sudo mkdir -p /etc/redis/cluster/{7000,7001,7002,7003,7004,7005}
sudo mkdir -p /var/lib/redis/cluster/{7000,7001,7002,7003,7004,7005}
sudo mkdir -p /var/log/redis/cluster/{7000,7001,7002,7003,7004,7005}

# Sahiplik ayarla
sudo chown -R redis:redis /etc/redis/cluster
sudo chown -R redis:redis /var/lib/redis/cluster
sudo chown -R redis:redis /var/log/redis/cluster

7000 numaralı port için örnek konfigürasyon dosyası:

sudo tee /etc/redis/cluster/7000/redis.conf << 'EOF'
# Temel ayarlar
port 7000
bind 0.0.0.0
protected-mode no
daemonize yes
pidfile /var/run/redis/cluster-7000.pid
logfile /var/log/redis/cluster/7000/redis.log

# Cluster ayarları
cluster-enabled yes
cluster-config-file /etc/redis/cluster/7000/nodes.conf
cluster-node-timeout 5000

# Veri persistansı
appendonly yes
appendfilename "appendonly.aof"
dir /var/lib/redis/cluster/7000/

# Bellek limiti
maxmemory 2gb
maxmemory-policy allkeys-lru

# Performans ayarları
tcp-backlog 511
timeout 0
tcp-keepalive 300
hz 10
EOF

Bu konfigürasyonu diğer portlar için de tekrarla. Hızlıca yapmak için:

for port in 7001 7002 7003 7004 7005; do
  sudo cp /etc/redis/cluster/7000/redis.conf /etc/redis/cluster/${port}/redis.conf
  sudo sed -i "s/7000/${port}/g" /etc/redis/cluster/${port}/redis.conf
done

Node’ları Başlatma

Her node’u ayrı ayrı başlat:

for port in 7000 7001 7002 7003 7004 7005; do
  sudo redis-server /etc/redis/cluster/${port}/redis.conf
  echo "Port ${port} baslatildi"
done

# Çalışıyor mu kontrol et
ps aux | grep redis-server

Çalışan process’leri daha temiz görmek için:

redis-cli -p 7000 ping
# PONG

# Tüm portları kontrol et
for port in 7000 7001 7002 7003 7004 7005; do
  result=$(redis-cli -p ${port} ping 2>&1)
  echo "Port ${port}: ${result}"
done

Cluster’ı Oluşturma

Artık gerçek adım geliyor. redis-cli --cluster create komutuyla cluster’ı bir hamlede kurabilirsin:

redis-cli --cluster create 
  127.0.0.1:7000 
  127.0.0.1:7001 
  127.0.0.1:7002 
  127.0.0.1:7003 
  127.0.0.1:7004 
  127.0.0.1:7005 
  --cluster-replicas 1

Buradaki --cluster-replicas 1 parametresi her master için bir replica oluşturulacağını söyler. Komut çalışınca Redis sana şöyle bir öneri sunacak:

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
Can I set the above configuration? (type 'yes' to accept):

yes yaz ve cluster kurulumu tamamlanır.

Gerçek ortamda farklı sunuculardaki IP’leri kullanırsın:

redis-cli --cluster create 
  192.168.1.10:6379 
  192.168.1.11:6379 
  192.168.1.12:6379 
  192.168.1.13:6379 
  192.168.1.14:6379 
  192.168.1.15:6379 
  --cluster-replicas 1

Cluster Durumunu Kontrol Etme

Cluster’ın sağlıklı çalışıp çalışmadığını birkaç farklı şekilde kontrol edebilirsin:

# Cluster bilgisi
redis-cli -p 7000 cluster info

# Çıktıda şunları görmek istersin:
# cluster_enabled:1
# cluster_state:ok
# cluster_slots_assigned:16384
# cluster_known_nodes:6
# cluster_size:3

# Node listesi
redis-cli -p 7000 cluster nodes

# Detaylı cluster kontrolü
redis-cli --cluster check 127.0.0.1:7000

cluster nodes çıktısında her satır bir node’u temsil eder. master veya slave rolünü, bağlantı durumunu ve slot aralıklarını görürsün.

Veri Yazma ve Okuma Testleri

Cluster modunda redis-cli kullanırken -c parametresi şarttır. Aksi halde MOVED hatası alırsın:

# Cluster modunda bağlan
redis-cli -c -p 7000

# Veri yaz
SET kullanici:1001 "Ahmet Yilmaz"
SET kullanici:1002 "Fatma Kaya"
SET urun:5001 "Laptop"

# Otomatik yönlendirme görebilirsin:
# -> Redirected to slot [xxxxx] located at 127.0.0.1:7002

Birden fazla node’a dağılan veriyi doğrulamak için her node’da key sayısını kontrol et:

for port in 7000 7001 7002; do
  count=$(redis-cli -p ${port} dbsize)
  echo "Master ${port}: ${count} key"
done

Yeni Node Ekleme ve Resharding

Production’da en sık yapılan işlemlerden biri yeni node eklemektir. Diyelim ki trafik arttı ve yeni bir master ekliyorsun:

# Önce yeni node'u başlat (port 7006)
redis-server /etc/redis/cluster/7006/redis.conf

# Cluster'a ekle
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000

# Yeni node şu an boş, slot yok
redis-cli -p 7006 cluster nodes | grep myself

# Resharding ile slot'ları dağıt
redis-cli --cluster reshard 127.0.0.1:7000

Reshard işlemi sırasında kaç slot taşımak istediğini, hedef node ID’sini ve kaynak node’ları sorар. Bu işlem production’da dikkatli yapılmalıdır. Taşınan slot sayısına göre işlem uzun sürebilir ve CPU kullanımı artabilir.

Resharding’i script ile otomatikleştirmek için:

redis-cli --cluster reshard 127.0.0.1:7000 
  --cluster-from all 
  --cluster-to <YENI_NODE_ID> 
  --cluster-slots 1000 
  --cluster-yes

Failover Senaryosu

Redis Cluster’ın en güçlü özelliklerinden biri otomatik failover’dır. Bir master node çöktüğünde, o node’un replica’sı belirli bir süre sonra otomatik master olur.

# Mevcut durumu gör
redis-cli -p 7000 cluster nodes

# 7000 portundaki master'ı simüle ederek öldür
sudo kill -9 $(cat /var/run/redis/cluster-7000.pid)

# Birkaç saniye bekle (cluster-node-timeout kadar)
sleep 10

# Failover oldu mu kontrol et
redis-cli -p 7001 cluster nodes
# 7000'in replica'sı olan node artık master olarak görünmeli

Manuel failover da yapabilirsin. Örneğin planlı bakım sırasında:

# Replica node'a bağlan ve manuel failover başlat
redis-cli -p 7003 cluster failover

# Zorla failover (master'a ulaşılamasa bile)
redis-cli -p 7003 cluster failover force

Uygulama Tarafında Cluster Bağlantısı

Redis Cluster’a uygulama tarafından bağlanırken normal bağlantı string’i çalışmaz. Node aware bir client kullanman gerekir.

Python için redis-py-cluster veya güncel redis paketi:

from redis.cluster import RedisCluster

# Startup nodes tanımla (hepsi olması şart değil, biri yeter)
startup_nodes = [
    {"host": "192.168.1.10", "port": "6379"},
    {"host": "192.168.1.11", "port": "6379"},
    {"host": "192.168.1.12", "port": "6379"},
]

rc = RedisCluster(
    startup_nodes=startup_nodes,
    decode_responses=True,
    skip_full_coverage_check=True
)

rc.set("oturum:abc123", "kullanici_verisi", ex=3600)
deger = rc.get("oturum:abc123")
print(deger)

Node.js için ioredis:

const Redis = require('ioredis');

const cluster = new Redis.Cluster([
  { host: '192.168.1.10', port: 6379 },
  { host: '192.168.1.11', port: 6379 },
  { host: '192.168.1.12', port: 6379 },
], {
  redisOptions: {
    password: 'gizli_sifre',
  },
  enableReadyCheck: true,
  maxRetriesPerRequest: 3,
});

cluster.set('sepet:kullanici1', JSON.stringify({ urun: ['laptop', 'mouse'] }));

İzleme ve Bakım Komutları

Cluster’ı sağlıklı tutmak için düzenli kontrol şarttır. Birkaç faydalı komut:

# Tüm cluster bilgisini özetle göster
redis-cli --cluster info 127.0.0.1:7000

# Hangi key hangi slot'ta?
redis-cli -p 7000 cluster keyslot "kullanici:1001"

# Belirli bir slot'taki key sayısı
redis-cli -p 7000 cluster countkeysinslot 5000

# Yavaş sorguları izle
redis-cli -p 7000 slowlog get 10

# Gerçek zamanlı istatistik
redis-cli -p 7000 --stat

# Bellek kullanımı
redis-cli -p 7000 info memory | grep used_memory_human

Cluster sağlık durumunu otomatik izlemek için basit bir bash script:

#!/bin/bash
NODES=("7000" "7001" "7002" "7003" "7004" "7005")
ALERT=0

for port in "${NODES[@]}"; do
  status=$(redis-cli -p ${port} ping 2>&1)
  if [ "$status" != "PONG" ]; then
    echo "UYARI: Port ${port} yanit vermiyor!"
    ALERT=1
  fi
done

# Cluster durumunu kontrol et
cluster_state=$(redis-cli -p 7000 cluster info | grep cluster_state | cut -d: -f2 | tr -d 'r')
if [ "$cluster_state" != "ok" ]; then
  echo "KRITIK: Cluster durumu: ${cluster_state}"
  ALERT=1
fi

if [ $ALERT -eq 0 ]; then
  echo "Cluster saglıklı calisiyor."
fi

Yaygın Sorunlar ve Çözümleri

CLUSTERDOWN hatası: Tüm slot’lar cover edilmiyorsa bu hata gelir. Genellikle bir master çökünce ve replica’sı da yokken oluşur.

# Hangi slotlar eksik?
redis-cli --cluster check 127.0.0.1:7000

# Acil durum: cluster_require_full_coverage'ı kapat
redis-cli -p 7000 config set cluster-require-full-coverage no

MOVED yönlendirmesi sorunları: Uygulama MOVED hatasını handle edemiyorsa cluster-aware client kullanmıyorsundur. Bunu asla görmezden gelme.

Yüksek bellek kullanımı: Her node’da maxmemory politikasını kontrol et:

redis-cli -p 7000 config get maxmemory
redis-cli -p 7000 config get maxmemory-policy

# Tüm node'larda değiştir
for port in 7000 7001 7002; do
  redis-cli -p ${port} config set maxmemory-policy allkeys-lru
done

Replica’ların master’a yetişememesi (replication lag):

# Replica'daki lag'i kontrol et
redis-cli -p 7003 info replication | grep master_repl_offset
redis-cli -p 7003 info replication | grep slave_repl_offset

Güvenlik Ayarları

Production ortamında cluster’ı açık bırakmamalısın:

# Her node için şifre ekle
redis-cli -p 7000 config set requirepass "guclu_sifre_buraya"

# Konfigürasyon dosyasına da yaz
echo "requirepass guclu_sifre_buraya" >> /etc/redis/cluster/7000/redis.conf
echo "masterauth guclu_sifre_buraya" >> /etc/redis/cluster/7000/redis.conf

# Tehlikeli komutları devre dışı bırak
redis-cli -p 7000 config set rename-command FLUSHALL ""
redis-cli -p 7000 config set rename-command DEBUG ""

Firewall kuralları da ihmal edilmemeli. Redis Cluster hem client portunu (6379 veya istediğin port) hem de cluster bus portunu (client port + 10000, yani 16379) kullanır:

# UFW ile örnek
sudo ufw allow from 192.168.1.0/24 to any port 7000:7005 proto tcp
sudo ufw allow from 192.168.1.0/24 to any port 17000:17005 proto tcp

Sonuç

Redis Cluster kurulumu ilk bakışta karmaşık görünse de temel mantığı kavradıktan sonra oldukça yönetilebilir bir yapı. Hash slot tabanlı sharding sistemi sayesinde veriler node’lara dengeli dağılıyor, otomatik failover sayesinde tek node’luk arızalar sistemi durdurmaktan çıkıyor.

Üretim ortamında dikkat etmen gereken birkaç kritik nokta var: Her zaman en az 3 master node kullan, aksi halde quorum sağlanamaz. Node’ları farklı fiziksel sunuculara veya en azından farklı sanal makine host’larına koy. Resharding işlemlerini yoğun trafik saatlerinden kaçınarak yap. Ve en önemlisi, monitoring’i ihmal etme; bir node sessizce down olabilir ve fark etmezsen replica kaybedersin.

Redis Cluster production’da çalıştığında, daha önce tek node’la yaşadığın bellek ve performans sınırlamalarının ortadan kalktığını göreceksin. Yatay ölçekleme artık gerçekten bir seçenek haline geliyor.

Yorum yapın