Redis'i önbellek olarak kurup unuttunuz, altı ay sorunsuz çalıştı, sonra bir gün sunucu yeniden başladı ve içindeki her şey gitti. Eğer orada tuttuğunuz şey gerçekten sadece önbellekse sorun yok; ama oturum verisi, kuyruk, sayaç ya da geçici olmayan başka bir şey tutuyorsanız bu kayıp doğrudan kullanıcıya yansır. Redis persistence, yani kalıcılık, tam olarak bunun ne kadarının kabul edilebilir olduğuna karar vermenizi ister ve size iki farklı mekanizma sunar: RDB anlık görüntüleri ve AOF günlüğü.
Bu rehberde RDB ile AOF'un nasıl çalıştığını, hangi durumda ne kadar veri kaybettireceğini, appendfsync politikalarının gerçekte ne anlama geldiğini, ikisini birlikte kullanmanın neden çoğu kurulum için doğru cevap olduğunu, AOF yeniden yazma (rewrite) sürecinin bellek ve disk maliyetini ve yeniden başlatmada verinin nasıl geri yüklendiğini anlatacağım. Sonunda da üretimde en çok can yakan yapılandırma hatalarını topladım.
Kalıcılık Neden Bir Karar Gerektirir#
Redis verisini bellekte tutar; hızının kaynağı budur. Diskteki kalıcılık, o bellek içeriğinin bir kopyasını çıkarma işidir ve her kopyalama biçimi hız, disk kullanımı ve veri kaybı riski arasında farklı bir denge kurar. Hiçbir kalıcılık kullanmamak da geçerli bir seçimdir — yeter ki bilinçli olsun.
Kararı vermek için kendinize tek bir soru sorun: bu Redis örneği çökerse ve içindeki her şey kaybolursa ne olur? Cevap "veriler zaten veritabanında var, önbellek yeniden dolar" ise kalıcılığı tamamen kapatabilirsiniz ve bu, en yüksek performansı verir. Cevap "kullanıcılar oturumlarından düşer" ise birkaç dakikalık kayıp kabul edilebilir olabilir. Cevap "işlenmemiş kuyruk mesajları kaybolur" ise en katı ayara ihtiyacınız var.
| Kullanım | Kabul edilebilir kayıp | Önerilen yapılandırma |
|---|---|---|
| Saf önbellek (cache) | Tamamı | Kalıcılık kapalı |
| Oturum deposu | Birkaç dakika | RDB, sık aralık |
| Sayaç, rate limit | Saniyeler | AOF everysec |
| İş kuyruğu, kritik veri | Neredeyse sıfır | AOF everysec + replika |
Redis'in bir veritabanı yerine geçip geçemeyeceği ayrı bir tartışma; ama şunu net söylemek gerekir: en katı ayarla bile Redis, tek başına ACID garantisi veren bir veritabanının yerini tutmaz. Kalıcılık burada "çökmeden sonra makul bir noktadan devam edebilme" anlamına gelir.
RDB: Anlık Görüntü (Snapshot)#
RDB, belirli aralıklarla bellekteki tüm veri kümesinin sıkıştırılmış bir kopyasını tek bir dosyaya yazar. Bu dosya, verinin o andaki tam ve tutarlı bir fotoğrafıdır. Yapılandırması redis.conf içinde save satırlarıyla yapılır ve söz dizimi "şu kadar saniyede şu kadar anahtar değiştiyse kaydet" biçimindedir.
# /etc/redis/redis.conf
# 900 saniyede en az 1 anahtar değiştiyse kaydet
save 900 1
# 300 saniyede en az 10 anahtar değiştiyse kaydet
save 300 10
# 60 saniyede en az 10000 anahtar değiştiyse kaydet
save 60 10000
dbfilename dump.rdb
dir /var/lib/redis
# RDB yazımı başarısız olursa yazma işlemlerini reddet (güvenli varsayılan)
stop-writes-on-bgsave-error yes
# Dosyayı sıkıştır (CPU biraz artar, disk ciddi azalır)
rdbcompression yes
rdbchecksum yes
RDB'nin çalışma biçimi zekicedir: Redis fork() ile bir alt süreç oluşturur, alt süreç belleğin o anki halini diske yazarken ana süreç isteklere cevap vermeye devam eder. İşletim sisteminin copy-on-write mekanizması sayesinde bellek baştan kopyalanmaz, yalnızca yazma sırasında değişen sayfalar çoğaltılır.
Bu mekanizmanın maliyeti şudur ve gözden kaçarsa sunucu çökertir: fork() sırasında yazma yoğunsa bellek kullanımı iki katına kadar çıkabilir. 8 GB veri tutan bir Redis, snapshot alırken kısa süreliğine 12-16 GB kullanabilir. Sunucuda o kadar boş RAM yoksa OOM killer devreye girer ve Redis öldürülür. Bu yüzden kalıcılık kullanan bir Redis sunucusunda bellek kullanımını fiziksel RAM'in yarısında tutmak yaygın bir kuraldır.
Elle snapshot almak için iki komut vardır ve aralarındaki fark önemlidir:
# BGSAVE: arka planda çalışır, sunucu bloklanmaz — üretimde bunu kullanın
redis-cli BGSAVE
# SAVE: ana süreçte çalışır, bitene kadar TÜM istekleri bloklar — üretimde kullanmayın
# redis-cli SAVE
# Son başarılı kaydın zaman damgası
redis-cli LASTSAVE
# Devam eden bir kayıt var mı
redis-cli INFO persistence | grep -E 'rdb_bgsave_in_progress|rdb_last_bgsave_status'
AOF: Her Yazma İşleminin Günlüğü#
AOF (Append Only File), veri kümesini değil işlemleri kaydeder. Redis'e gelen her yazma komutu, aynı protokol biçiminde bir dosyanın sonuna eklenir. Yeniden başlatmada Redis bu komutları baştan sona tekrar oynatarak veriyi yeniden inşa eder.
appendonly yes
appendfilename "appendonly.aof"
appenddirname "appendonlydir"
# fsync politikası — asıl karar burada
appendfsync everysec
# Yeniden yazma sırasında fsync'i durdur (latency için iyi, risk için kötü)
no-appendfsync-on-rewrite no
# Dosya bir öncekine göre %100 büyüdüğünde ve en az 64mb olduğunda yeniden yaz
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
Asıl karar appendfsync satırındadır çünkü veri kaybı riskini doğrudan bu belirler. Redis komutu dosyaya yazar ama bu yazma işletim sisteminin tamponunda kalabilir; gerçekten diske inmesi fsync çağrısıyla olur.
appendfsync | Ne yapar | Olası kayıp | Performans |
|---|---|---|---|
always | Her komuttan sonra fsync | Neredeyse sıfır | Çok düşük throughput |
everysec | Saniyede bir fsync | En fazla ~1 saniye | Neredeyse tam hız |
no | fsync'i işletim sistemine bırak | 30 saniyeye kadar | En hızlı |
everysec neredeyse her zaman doğru cevaptır: en fazla bir saniyelik kayıp riskine karşılık always ayarının yarattığı devasa gecikme cezasını ödemezsiniz. always yalnızca finansal işlem gibi tek bir komutun kaybının bile kabul edilemez olduğu, buna karşılık işlem hacminin düşük olduğu durumlarda mantıklıdır.
AOF dosyası sürekli büyür çünkü aynı anahtara yapılan bin ayrı INCR bin ayrı satır olarak durur. Bunu engellemek için Redis periyodik olarak rewrite yapar: mevcut veri kümesini üretecek en kısa komut dizisini yeni bir dosyaya yazar ve eskisini atar.
# Elle yeniden yazma tetikle
redis-cli BGREWRITEAOF
# Durumu izle
redis-cli INFO persistence | grep -E 'aof_enabled|aof_rewrite_in_progress|aof_last_bgrewrite_status|aof_last_write_status'
Rewrite işlemi de fork() kullanır; yani RDB için anlattığım bellek ikiye katlanma riski burada da geçerlidir. Modern Redis sürümlerinde AOF, tek bir dev dosya yerine bir manifest ve birden fazla artımlı dosyadan oluşan bir dizin yapısında tutulur; bu, rewrite sırasındaki disk ve IO baskısını azaltır.
İkisini Birlikte Kullanmak#
RDB ve AOF birbirinin alternatifi gibi sunulur ama üretimde doğru cevap çoğu zaman ikisini birden açmaktır. Mantık şudur: AOF düşük veri kaybı sağlar, RDB ise hızlı yeniden başlatma ve kolay taşınabilir yedek sağlar. Redis yeniden başladığında AOF etkinse veriyi ondan yükler, RDB dosyası ise elinizde tek dosyalık bir yedek olarak durur.
Modern Redis'te bu birlikteliği daha da verimli kılan bir özellik var: hibrit kalıcılık. AOF yeniden yazması sırasında dosyanın başına RDB biçiminde bir anlık görüntü, sonrasına da o andan itibaren gelen komutlar yazılır. Böylece hem hızlı yükleme hem düşük kayıp elde edilir.
# Her ikisi de açık
appendonly yes
appendfsync everysec
save 900 1
save 300 10
save 60 10000
# Hibrit format: AOF'un başında RDB anlık görüntüsü (varsayılan olarak açık)
aof-use-rdb-preamble yes
Yeniden başlatma davranışını bilmek önemlidir: AOF açıksa Redis RDB dosyasını görmezden gelir. AOF dosyasını yanlışlıkla silip Redis'i yeniden başlatırsanız, elinizde geçerli bir RDB olsa bile boş bir veri kümesiyle açılır. Bu, "yedek vardı ama geri gelmedi" hikâyelerinin en yaygın sebebidir.
# Yeniden başlatmadan önce hangi dosyaların olduğunu kontrol edin
sudo ls -lh /var/lib/redis/
# dump.rdb appendonlydir/
# Yükleme kaynağını doğrulayın
redis-cli INFO persistence | grep -E 'loading|aof_enabled'
Yedekleme, Geri Yükleme ve Doğrulama#
RDB dosyası tek başına taşınabilir bir yedektir ve kopyalaması güvenlidir; Redis onu atomik biçimde yazar (geçici dosyaya yazıp sonra yeniden adlandırır), dolayısıyla yarım bir dosya kopyalama riski yoktur. Pratik bir yedekleme rutini şöyle kurulur:
#!/usr/bin/env bash
# Redis RDB yedeği alıp tarih damgalı olarak saklar
set -euo pipefail
HEDEF=/yedek/redis
mkdir -p "$HEDEF"
# Yeni bir snapshot tetikle ve bitmesini bekle
ONCEKI=$(redis-cli LASTSAVE)
redis-cli BGSAVE > /dev/null
while [ "$(redis-cli LASTSAVE)" = "$ONCEKI" ]; do sleep 1; done
cp /var/lib/redis/dump.rdb "$HEDEF/dump-$(date -u +%Y%m%dT%H%M%SZ).rdb"
find "$HEDEF" -name 'dump-*.rdb' -mtime +14 -delete
Geri yükleme sırası şudur ve ilk adım atlanırsa kopyaladığınız dosya anında üzerine yazılır:
- Redis servisini durdurun.
- Yedek RDB dosyasını
dirayarındaki dizinedump.rdbadıyla kopyalayın. - AOF kullanıyorsanız AOF dizinini temizleyin, aksi halde Redis AOF'tan yükler ve RDB'nizi yok sayar.
- Dosya sahipliğini
redis:redisyapın. - Servisi başlatın ve
DBSIZEile anahtar sayısını doğrulayın.
sudo systemctl stop redis-server
sudo cp /yedek/redis/dump-20260825T030000Z.rdb /var/lib/redis/dump.rdb
sudo rm -rf /var/lib/redis/appendonlydir # AOF kullanılıyorsa
sudo chown redis:redis /var/lib/redis/dump.rdb
sudo systemctl start redis-server
redis-cli DBSIZE
Bozuk bir AOF dosyasını onarmak için Redis kendi aracını sunar. Önce dosyanın kopyasını alın, sonra kontrol edin:
# Sadece doğrula
redis-check-aof /var/lib/redis/appendonlydir/appendonly.aof.1.incr.aof
# Bozuk kuyruğu kesip onar (geri alınamaz — önce kopyasını alın)
redis-check-aof --fix /var/lib/redis/appendonlydir/appendonly.aof.1.incr.aof
# RDB için karşılığı
redis-check-rdb /var/lib/redis/dump.rdb
Yedeklerinizi mutlaka Redis sunucusunun dışında bir yerde saklayın; aynı diskteki bir yedek disk arızasında beraber gider. Düzenli kopyalar için yedekleme hizmetimiz ya da ikinci bir sunucu hedefi pratik bir çözümdür.
Sık Yapılan Hatalar ve Tuzaklar#
stop-writes-on-bgsave-error ayarını anlamadan kapatmak. Bu ayar açıkken, snapshot yazımı başarısız olursa Redis yazma komutlarını reddeder ve uygulamanız hata almaya başlar. İlk tepki ayarı kapatmak olur; oysa ayar sizi uyarıyordur. Gerçek sorun genelde dolu disk ya da yanlış dizin izinleridir. Kapatmadan önce INFO persistence çıktısındaki rdb_last_bgsave_status değerine bakın.
Yetersiz RAM ile fork. Snapshot ve AOF rewrite işlemleri fork() kullanır ve yazma yoğunsa bellek kullanımı belirgin biçimde artar. Redis'e fiziksel RAM'in tamamını ayırmak, ilk snapshot denemesinde OOM killer'ın devreye girmesi demektir. maxmemory değerini fiziksel belleğin yarısı civarında tutun.
vm.overcommit_memory ayarını atlamak. Linux varsayılan ayarında fork() çağrısı, gerçekte gerekmese bile yeterli bellek olmadığı gerekçesiyle başarısız olabilir. Redis başlangıçta bu konuda uyarı basar ve çözüm tek satırlıktır:
echo 'vm.overcommit_memory = 1' | sudo tee /etc/sysctl.d/99-redis.conf
sudo sysctl -p /etc/sysctl.d/99-redis.conf
AOF dosyasını silip RDB'nin devreye gireceğini sanmak. AOF etkinse Redis yalnızca AOF'tan yükler. Geri yükleme yaparken AOF'u kapatmadan veya AOF dizinini temizlemeden RDB kopyalamak hiçbir işe yaramaz.
Yedeği hiç test etmemek. RDB dosyanız her gece kopyalanıyor olabilir ama geri yüklemeyi hiç denemediyseniz elinizde ne olduğunu bilmiyorsunuz demektir. Ayda bir kez ayrı bir Redis örneğine yükleyip DBSIZE ve birkaç anahtarı kontrol edin.
Kalıcılığı yüksek yazma yükünde always ile çalıştırmak. appendfsync always her komutta diske senkron yazma yapar; NVMe diskte bile throughput'u kat kat düşürür. Gerçekten gerekiyorsa ölçün, gerekmiyorsa everysec kullanın.
Sıkça Sorulan Sorular#
RDB mi AOF mu kullanmalıyım#
Çoğu üretim kurulumu için doğru cevap ikisini birden açmaktır. AOF everysec ile veri kaybını bir saniyeye indirir, RDB ise hızlı yeniden başlatma ve tek dosyalık taşınabilir yedek sağlar. Yalnızca birini seçmeniz gerekiyorsa, Redis'i önbellek olarak kullanıyorsanız RDB (hatta hiçbiri), kalıcı veri tutuyorsanız AOF tercih edin. İkisini birlikte kullanmanın maliyeti çoğunlukla ihmal edilebilir düzeydedir.
Redis kalıcılık açıkken ne kadar yavaşlar#
appendfsync everysec ayarında fark çoğu iş yükünde ölçülebilir ama küçüktür, çünkü fsync saniyede bir kez ve ayrı bir iş parçacığında yapılır. always ayarında ise her yazma komutu diske senkron inmeyi beklediği için throughput ciddi biçimde düşer; disk hızına bağlı olarak birkaç kat fark görebilirsiniz. RDB'nin sürekli bir maliyeti yoktur; yalnızca snapshot anında CPU ve bellek baskısı oluşur.
AOF dosyası neden bu kadar büyüdü#
Çünkü AOF her yazma komutunu ekler ve aynı anahtara yapılan tekrarlı işlemler dosyada ayrı ayrı durur. Redis bunu auto-aof-rewrite-percentage ayarına göre periyodik olarak temizler; dosya bir önceki yeniden yazmadan bu oranda büyüdüğünde otomatik rewrite tetiklenir. Rewrite hiç tetiklenmiyorsa ya ayar kapatılmıştır (0 yapılmıştır) ya da yeterli disk alanı olmadığı için başarısız oluyordur; INFO persistence çıktısındaki aof_last_bgrewrite_status değerine bakın.
Redis çökerse ne kadar veri kaybederim#
Yapılandırmanıza bağlıdır. Kalıcılık kapalıysa her şeyi. Yalnızca RDB kullanıyorsanız son başarılı snapshot'tan bu yana geçen süredeki tüm değişiklikleri — bu, save aralıklarınıza göre dakikalar olabilir. AOF everysec ile en fazla yaklaşık bir saniyelik yazma kaybedersiniz. AOF always ile kayıp neredeyse sıfırdır ama performans bedeli yüksektir.
Yedeği canlı Redis çalışırken kopyalayabilir miyim#
RDB dosyasını evet, güvenle kopyalayabilirsiniz. Redis snapshot'ı önce geçici bir dosyaya yazıp sonra atomik olarak yeniden adlandırdığı için dump.rdb her zaman tutarlı bir dosyadır. En sağlıklısı önce BGSAVE çalıştırıp LASTSAVE değerinin değişmesini beklemek, sonra kopyalamaktır. AOF dizinini kopyalarken ise rewrite sürüyorsa tutarsız bir an yakalayabilirsiniz; AOF yedeği için de RDB tabanlı yaklaşım daha güvenlidir.
Kalıcılığı tamamen kapatmak mantıklı mı#
Redis'i saf önbellek olarak kullanıyorsanız ve içindeki her şey kaynak veritabanından yeniden üretilebiliyorsa evet, tamamen mantıklıdır ve en yüksek performansı verir. Bu durumda save "" ve appendonly no ayarlarıyla diske hiç yazmazsınız, fork kaynaklı bellek sıçramaları da ortadan kalkar. Yalnız şunu doğrulayın: uygulamanız boş bir önbellekle açıldığında kaynak veritabanına gelen ani yükü kaldırabiliyor mu? Bu "cache stampede" durumu, kalıcılığı kapatmadan önce düşünülmesi gereken asıl risktir.
Kapanış#
Redis kalıcılığında doğru yapılandırma, ne kadar veri kaybını göze aldığınıza bağlı olarak değişir; sihirli tek bir ayar yok. Aklınızda tutun: çoğu üretim kurulumu için AOF everysec artı RDB birlikte doğru cevaptır, AOF açıkken Redis RDB'yi görmezden gelir, fork() yüzünden bellek kullanımı geçici olarak sıçrayabileceği için maxmemory değerini fiziksel RAM'in yarısında tutun ve yedeğinizi geri yüklemeyi gerçekten prova edin. Bir de stop-writes-on-bgsave-error uyarısını kapatarak değil, sebebini bularak çözün.
Kalıcılık açık bir Redis'in ihtiyacı hızlı disk ve rahat bellektir. NVMe diskli VDS veya belleği esnek büyütülebilen bulut sunucu paketlerimiz bu iş yükü için uygun bir taban sunar; RDB yedeklerinizi sunucu dışında saklamak için yedekleme hizmetimizden yararlanabilirsiniz. Kurulum, ayar ve izleme işlerini devretmek isterseniz sunucu yönetimi hizmetimiz Redis tarafını da kapsıyor.