Redis’te bir anahtara yaşam süresi (time to live, TTL) vermek için EXPIRE anahtar saniye komutu kullanılır; süre dolduğunda anahtar kendiliğinden silinir. Kalan süreyi TTL (saniye) ya da PTTL (milisaniye) ile okursunuz. Yanıt -1 ise anahtar var ama süresi yoktur, -2 ise anahtar hiç yoktur. Süreyi kaldırıp anahtarı kalıcı yapmak için PERSIST kullanılır. Süresi olan anahtara Redis terminolojisinde “volatile” denir.
Bu yazıda EXPIRE ailesinin bütün komutlarını, NX, XX, GT, LT koşullarını, hangi komutların süreyi silip hangilerinin koruduğunu ve Redis’in süresi dolan anahtarları arka planda nasıl temizlediğini resmî belgelere göre anlatıyoruz. Hash içindeki tek tek alanlara süre vermek ayrı bir özellik olduğu için onu hash alan süresi yazısına bıraktık. Serinin genel planı için Redis öğrenme rehberine bakın.
Süre dolması nasıl çalışır?
Normalde Redis anahtarları süresiz oluşturulur ve siz açıkça silene kadar yaşar. EXPIRE ailesi bir anahtara süre ekler; bunun bedeli anahtar başına biraz ek bellektir. Belge, süre konusunda bilmeniz gereken üç temel noktayı şöyle sıralar: süreyi saniye veya milisaniye hassasiyetiyle verebilirsiniz; ama süre çözünürlüğü her zaman 1 milisaniyedir; süre bilgisi çoğaltılır ve diske kaydedilir. Son madde önemlidir: Redis süreyi “kaç saniye kaldı” olarak değil, anahtarın sona ereceği mutlak Unix zaman damgası olarak saklar. Bu yüzden sunucu kapalıyken de zaman akmaya devam eder.
Belgedeki ilk örnek süreyi gözle görülür biçimde gösterir. Anahtara 5 saniye verilir; hemen yapılan okuma değeri döndürür, bir süre sonra yapılan okuma ise boş yanıt alır:
> set key some-value
OK
> expire key 5
(integer) 1
> get key (immediately)
"some-value"
> get key (after some time)
(nil)Buradaki (immediately) ve (after some time) ifadeleri komutun parçası değildir; belgede iki okumanın zamanını anlatmak için eklenmiş notlardır. EXPIRE komutunun yanıtı 1 ise süre ayarlanmıştır; 0 ise ayarlanmamıştır, örneğin anahtar yoktur ya da verdiğiniz koşul sağlanmamıştır.
EXPIRE seçenekleri: NX, XX, GT ve LT

EXPIRE dört koşul seçeneği alır ve bunlar birbirini dışlar. NX süreyi yalnızca anahtarın süresi yoksa, XX yalnızca zaten bir süresi varsa ayarlar. GT yeni süre mevcut süreden büyükse, LT küçükse ayarlar. Belgedeki örnek önce düz bir süre verir, sonra değeri SET ile değiştirerek sürenin silindiğini gösterir ve XX ile NX farkını ortaya koyar:
> SET mykey "Hello"
OK
> EXPIRE mykey 10
(integer) 1
> TTL mykey
(integer) 10
> SET mykey "Hello World"
OK
> TTL mykey
(integer) -1
> EXPIRE mykey 10 XX
(integer) 0
> TTL mykey
(integer) -1
> EXPIRE mykey 10 NX
(integer) 1
> TTL mykey
(integer) 10Oturumu adım adım okuyalım. İkinci SET anahtarın değerini değiştirdiği için süre silinir ve TTL -1 döndürür. Ardından XX ile verilen süre reddedilir, çünkü anahtarın artık süresi yoktur. NX ile verilen süre ise kabul edilir.
GT ve LT için belgenin önemli bir notu vardır: süresi olmayan bir anahtar bu iki seçenek açısından sonsuz süreli kabul edilir. Bunun pratik sonucu şudur: kalıcı bir anahtara GT ile süre veremezsiniz, çünkü hiçbir süre sonsuzdan büyük değildir; LT ile ise verebilirsiniz. GT, “süreyi yalnızca uzat, asla kısaltma” kuralını uygulamak istediğiniz durumlar için uygundur; örneğin birden fazla işlemin aynı anahtarın süresini uzatmaya çalıştığı bir oturum modelinde kısa süreli bir isteğin uzun süreyi ezmesini önler.
| Seçenek | Süre ne zaman ayarlanır | Süresiz anahtarda |
|---|---|---|
| NX | Anahtarın süresi yoksa | Ayarlanır |
| XX | Anahtarın süresi varsa | Ayarlanmaz |
| GT | Yeni süre mevcuttan büyükse | Ayarlanmaz (süresiz sonsuz sayılır) |
| LT | Yeni süre mevcuttan küçükse | Ayarlanır (süresiz sonsuz sayılır) |
Süreyi hangi komutlar siler, hangileri korur?
Bu konu, süreli anahtarlarla çalışırken en çok karışıklık yaratan noktadır. Belgeye göre süre yalnızca anahtarın içeriğini silen veya tamamen yenisiyle değiştiren komutlarla temizlenir: DEL, SET, GETSET ve bütün *STORE komutları bu gruptadır. Değeri yerinde değiştiren, yani kavramsal olarak değeri yenisiyle değiştirmeyip üzerinde işlem yapan komutlar ise süreye dokunmaz. INCR ile sayıyı artırmak, LPUSH ile listeye eleman eklemek veya HSET ile bir hash alanını değiştirmek süreyi olduğu gibi bırakır.
| İşlem | Süreye etkisi |
|---|---|
| DEL, SET, GETSET, *STORE komutları | Süre silinir |
| INCR, LPUSH, HSET gibi yerinde değişiklik | Süre korunur |
| SET ... KEEPTTL | Süre korunur |
| PERSIST veya GETEX ... PERSIST | Süre kaldırılır, anahtar kalıcı olur |
| RENAME eski yeni | Süre yeni ada taşınır |
| RENAME ile var olan anahtarın üzerine yazmak | Hedef, kaynağın bütün özelliklerini devralır |
| EXPIRE ile tekrar süre vermek | Süre yeni değerle güncellenir |
Yeniden adlandırmanın iki ayrıntısı vardır. RENAME ile adı değiştirilen anahtarın süresi yeni ada geçer. RENAME Key_B Key_A gibi bir çağrıyla var olan bir Key_A ezilirse, eski Key_A anahtarının süresi olup olmaması önemli değildir: yeni Key_A, Key_B anahtarının bütün özelliklerini, süresi dahil, devralır. Belge ayrıca Redis 2.1.3 öncesinde süreli bir anahtarı değiştirmenin anahtarı tamamen sildiğini, bunun artık geçerli olmadığını not eder.
Süreyi güncellemek de serbesttir: süresi olan bir anahtara tekrar EXPIRE verdiğinizde süre yeni değerle değiştirilir. Bu, “her etkinlikte süreyi yenile” desenlerinin temelidir.
Sıfır, negatif süre ve geçmiş zaman damgası

EXPIRE veya PEXPIRE komutunu sıfır ya da negatif bir süreyle, EXPIREAT veya PEXPIREAT komutunu geçmişte kalan bir zamanla çağırırsanız anahtar süresi dolmuş gibi değil, doğrudan silinmiş gibi işlem görür. Belge bunun bir yan etkisini de belirtir: üretilen anahtar olayı expired değil del olur. Anahtar olaylarını dinleyen bir sisteminiz varsa bu fark önemlidir; ayrıntılar keyspace notifications yazısında.
Süre argümanı tamsayı olmalıdır. Resmî hata sayfası, sayı yerine metin verildiğinde dönen hatayı gösterir; 10s veya 2.5 gibi birimli ya da ondalıklı değerler de aynı hataya yol açar:
> EXPIRE counter ten
(error) ERR value is not an integer or out of rangeMilisaniye ve mutlak zaman: PEXPIRE, EXPIREAT, PEXPIREAT
PEXPIRE, EXPIRE ile tamamen aynı çalışır ama süreyi milisaniye olarak alır ve aynı dört koşul seçeneğini destekler. Belgedeki örnekte 1500 milisaniyelik süre TTL ile yuvarlanmış olarak 2, PTTL ile tam olarak 1500 görünür:
redis> SET mykey "Hello"
OK
redis> PEXPIRE mykey 1500
(integer) 1
redis> TTL mykey
(integer) 2
redis> PTTL mykey
(integer) 1500
redis> PEXPIRE mykey 1000 XX
(integer) 1
redis> TTL mykey
(integer) 1
redis> PEXPIRE mykey 1000 NX
(integer) 0
redis> TTL mykey
(integer) 1EXPIREAT ise göreli süre yerine 1 Ocak 1970’ten bu yana geçen saniye sayısıyla mutlak bir Unix zaman damgası alır. Belgeye göre bu komut aslında AOF kalıcılık modunda göreli süreleri mutlak sürelere çevirmek için eklenmiştir, ama bir anahtarın belirli bir anda sona ermesini istediğinizde doğrudan kullanılabilir. Geçmişte kalan bir zaman verirseniz anahtar hemen silinir:
redis> SET mykey "Hello"
OK
redis> EXISTS mykey
(integer) 1
redis> EXPIREAT mykey 1293840000
(integer) 1
redis> EXISTS mykey
(integer) 0PEXPIREAT aynı işi milisaniyelik zaman damgasıyla yapar. Belgedeki örnekte verilen zaman geçmişte kaldığı için anahtar silinir ve iki süre sorgusu da -2 döndürür:
redis> SET mykey "Hello"
OK
redis> PEXPIREAT mykey 1555555555005
(integer) 1
redis> TTL mykey
(integer) -2
redis> PTTL mykey
(integer) -2Kalan süreyi okumak: TTL, PTTL, EXPIRETIME
TTL kalan süreyi saniye, PTTL milisaniye olarak verir. İkisinde de -1 “anahtar var ama süresi yok”, -2 “anahtar yok” anlamına gelir. Belge, Redis 2.6 ve öncesinde iki durumun da -1 döndürdüğünü, ayrımın Redis 2.8 ile geldiğini not eder; çok eski bir sunucuyla çalışmıyorsanız bu ayrıma güvenebilirsiniz.
redis> SET mykey "Hello"
OK
redis> EXPIRE mykey 1
(integer) 1
redis> PTTL mykey
(integer) 1000Kalan süre yerine anahtarın tam olarak hangi anda sona ereceğini öğrenmek isterseniz EXPIRETIME mutlak Unix zamanını saniye, PEXPIRETIME milisaniye olarak döndürür. -1 ve -2 değerleri burada da aynı anlamı taşır:
redis> SET mykey "Hello"
OK
redis> EXPIREAT mykey 33177117420
(integer) 1
redis> EXPIRETIME mykey
(integer) 33177117420Süreyi kaldırmak için PERSIST kullanılır. Süre kaldırıldıysa 1, anahtar yoksa ya da zaten süresizse 0 döner:
redis> SET mykey "Hello"
OK
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10
redis> PERSIST mykey
(integer) 1
redis> TTL mykey
(integer) -1Süreli anahtarı tek komutta oluşturmak
Önce SET, sonra EXPIRE göndermek iki ayrı komuttur ve arada istemci çökerse anahtar süresiz kalabilir. Bu yüzden süreyi yazma komutunun içinde vermek daha güvenlidir. SET komutunun EX, PX, EXAT, PXAT seçenekleri bunu yapar; belgedeki örnek:
> set key 100 ex 10
OK
> ttl key
(integer) 9TTL komutunun 10 değil 9 döndürmesi, iki komut arasında geçen kısa süreyle açıklanabilir; süre saniye cinsinden aşağı yuvarlanmış görünür. Aynı amaçla SETEX, okuma sırasında süre vermek için GETEX, birden fazla anahtarı ortak süreyle yazmak için de Redis 8.4 ile gelen MSETEX kullanılabilir; bu komutların ayrıntısı string komutları yazısında.
Redis süresi dolan anahtarları nasıl siler?
Süre dolduğu anda anahtarın bellekten silindiğini düşünmek yaygın bir yanılgıdır. Belgeye göre Redis anahtarları iki yolla siler. Pasif yolda bir istemci anahtara erişmeye çalıştığında anahtarın süresinin dolduğu fark edilir ve anahtar silinir. Ancak hiç erişilmeyen anahtarlar da temizlenmelidir; bu yüzden aktif yolda Redis düzenli aralıklarla süreli anahtarlar arasından rastgele birkaç tanesini test eder ve süresi dolmuş olanları siler.
Bunun iki pratik sonucu vardır. Birincisi, süresi dolmuş bir anahtara erişmeye çalıştığınızda pasif silme devreye girer ve anahtar bulunamaz; yukarıdaki ilk örnekte ikinci GET komutunun boş yanıt alması bundandır. İkincisi, bellekten fiilen silinme ve buna bağlı expired olayı süre sıfıra indiği anda değil, anahtar bu iki mekanizmadan biriyle bulunduğunda gerçekleşir. Keyspace bildirimleri sayfası, çok sayıda süreli anahtar varken ve anahtara sürekli erişilmiyorken bu gecikmenin belirgin olabileceğini açıkça yazar.
Çoğaltma ve AOF tarafında tutarlılık için bir anahtarın süresi dolduğunda AOF dosyasına ve bağlı bütün kopyalara (replica) bir DEL işlemi gönderilir. Böylece süre dolma işlemi ana sunucuda merkezileşir. Kopyalar anahtarları kendi başlarına silmez, ana sunucudan gelecek DEL komutunu bekler; ama bütün süre bilgisini tuttukları için ana sunucu olarak seçildiklerinde süreleri bağımsız olarak işletebilirler.
Kullanım desenleri
Belgedeki “gezinme oturumu” deseni, sürenin yenilenmesini güzel gösterir. Kullanıcının son sayfa görüntülemelerini, aralarında 60 saniyeden fazla boşluk olmadığı sürece tutmak istediğinizi düşünün. Her sayfa görüntülemesinde şu komutlar gönderilir:
MULTI
RPUSH pagewviews.user:<userid> http://.....
EXPIRE pagewviews.user:<userid> 60
EXECKullanıcı 60 saniyeden uzun süre hareketsiz kalırsa anahtar silinir ve yalnızca bundan sonraki görüntülemeler kaydedilir. RPUSH süreye dokunmadığı ama EXPIRE süreyi her seferinde yeniden 60 yaptığı için liste kullanıcı aktif kaldıkça yaşar. Belge aynı desenin liste yerine INCR ile sayaç olarak da kurulabileceğini söyler; MULTI ve EXEC ise iki komutun birlikte çalışmasını sağlar (MULTI ve EXEC).
Sayaç ve süreyi birleştiren hız sınırlama desenleri için API rate limiting stratejileri yazısına, genel önbellek kavramları için önbellek nedir yazısına bakın. Bellek dolduğunda süreli anahtarları öncelikli silen volatile politikaları ise maxmemory ve eviction yazısında anlatılıyor.
Sık yapılan hatalar

- Değeri SET ile güncelleyip süreyi kaybetmek:
SETsüreyi siler;KEEPTTLekleyin ya da süreyi yeniden verin. - SET ve EXPIRE’ı ayrı göndermek: Arada hata olursa anahtar süresiz kalır;
SET ... EXkullanın. - TTL -1 ile -2’yi karıştırmak: -1 süresiz ama var olan anahtar, -2 hiç olmayan anahtardır.
- Süre dolunca anında olay beklemek:
expiredolayı silme anında üretilir ve gecikebilir. - Kalıcı anahtara GT ile süre vermeye çalışmak: Süresiz anahtar sonsuz sayıldığı için
GThiçbir zaman başarılı olmaz. - Süreyi birimle yazmak:
EXPIRE k 10shata verir; süre yalnızca tamsayıdır.
Sık Sorulan Sorular
TTL komutu -1 döndürüyor, ne anlama geliyor?
Anahtar var ama bir süresi yok; siz silene kadar kalıcıdır. -2 ise anahtarın hiç olmadığı anlamına gelir.
INCR süreli bir sayacın süresini sıfırlar mı?
Hayır. INCR değeri yerinde değiştirdiği için süre korunur. Süreyi yalnızca DEL, SET, GETSET ve *STORE komutları gibi değeri tamamen değiştiren işlemler siler.
Sunucu kapalıyken süre işlemeye devam eder mi?
Evet. Redis sona erme anını mutlak zaman damgası olarak saklar, bu yüzden sunucu kapalı kaldığı sürede de zaman akar. Sunucu açıldığında süresi geçmiş anahtarlar sona ermiş sayılır.
Hash içindeki tek bir alana süre verebilir miyim?
EXPIRE bütün anahtar için çalışır. Alan düzeyinde süre için Redis 7.4 ile gelen HEXPIRE ailesi vardır; hash alan süresi yazısına bakın.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Redis öğrenme rehberi · String komutları · Hash alan süresi · Keyspace notifications · Önbellek nedir