Redis keyspace notifications, veri setini etkileyen olayları (bir anahtarın silinmesi, bir listeye eleman eklenmesi, bir anahtarın süresinin dolması gibi) Pub/Sub kanalları üzerinden yayımlayan bir özelliktir. Varsayılan olarak kapalıdır; notify-keyspace-events ayarına hangi olay sınıflarını istediğinizi belirten harflerden oluşan bir dize verdiğinizde açılır. Olaylar iki tür kanala gider: __keyspace@0__:anahtar kanalı o anahtara olan her şeyi, __keyevent@0__:olay kanalı ise o olayın yaşandığı her anahtarı bildirir. Pub/Sub temelli olduğu için bağlantısı kopan istemci aradaki olayları kaybeder.

Bu yazıda iki bildirim türünü, yapılandırma harflerini, komutların hangi olayları ürettiğini, expired olayının neden gecikebileceğini, cluster davranışını ve Redis 8.8 ile gelen hash alanı düzeyindeki subkey bildirimlerini belgelere dayanarak anlatıyoruz. Pub/Sub'ın temelleri (SUBSCRIBE, PSUBSCRIBE, mesaj biçimi) Pub/Sub yazımızda anlatılıyor; serinin tamamı için Redis öğrenme rehberi sayfasına bakın.

Neler bildirilir?

Belgeler alınabilecek olaylara üç örnek verir: belirli bir anahtarı etkileyen tüm komutlar, LPUSH işlemi uygulanan tüm anahtarlar ve 0 numaralı veritabanında süresi dolan tüm anahtarlar. Bu esneklik iki farklı kanal ailesinden gelir. Bir istemci bu kanallara sıradan Pub/Sub komutlarıyla abone olur; Redis'in yaptığı tek şey, olay gerçekleştiğinde bu kanallara bir PUBLISH yapmaktır.

İki olay türü: keyspace ve keyevent

Veri uzayını etkileyen her işlem için iki ayrı olay gönderilir. Örneğin 0 numaralı veritabanındaki mykey anahtarını hedefleyen bir DEL işlemi, tam olarak aşağıdaki iki PUBLISH komutuna eşdeğer iki mesaj üretir:

text
PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey

Birinci kanal mykey anahtarını hedefleyen tüm olayları dinler ve mesaj olarak olayın adını (del) alır; buna key-space bildirimi denir. İkinci kanal yalnızca del olaylarını dinler ve mesaj olarak anahtarın adını (mykey) alır; buna key-event bildirimi denir. Hangisini seçeceğiniz sorunuza bağlıdır: "bu anahtara ne oldu?" sorusu için keyspace, "hangi anahtarların süresi doldu?" sorusu için keyevent kanalı uygundur. İhtiyacınız olan alt kümeyi almak için türlerden yalnızca birini açmak da mümkündür.

Yapılandırma: notify-keyspace-events harfleri

Yapılandırma: notify-keyspace-events harfleri: Keyspace olayları, __keyspace@__ ön ekiyle yayımlanır, Keyevent olayları, __keyevent@__ ön ekiyle yayımlanır, Tipe özgü olmayan...

Bildirimler varsayılan olarak kapalıdır, çünkü belgelerin ifadesiyle çok fazla olmasa da biraz CPU gücü harcarlar. Açmak için redis.conf içindeki notify-keyspace-events ayarı ya da CONFIG SET kullanılır. Boş dize bildirimleri kapatır; her harfin özel bir anlamı olan boş olmayan bir dize ise açar:

HarfAnlamı
KKeyspace olayları, __keyspace@<db>__ ön ekiyle yayımlanır
EKeyevent olayları, __keyevent@<db>__ ön ekiyle yayımlanır
gTipe özgü olmayan genel komutlar: DEL, EXPIRE, RENAME ...
$String komutları
lList komutları
sSet komutları
hHash komutları
zSorted set komutları
tStream komutları
aArray komutları
dModül anahtar tipi olayları
xSüresi dolma (expired) olayları
emaxmemory nedeniyle çıkarma (evicted) olayları
mVar olmayan anahtara erişim (key miss) olayları, A sınıfına dahil değil
nYeni anahtar olayları, A sınıfına dahil değil
oÜzerine yazılma (overwritten) olayları, A sınıfına dahil değil
cTip değişikliği (type_changed) olayları, A sınıfına dahil değil
Ag$lshztdxea için kısaltma

Dizede en az K ya da E bulunmalıdır; ikisi de yoksa dizenin geri kalanı ne olursa olsun hiçbir olay teslim edilmez. Örneğin yalnızca listeler için key-space olaylarını açmak istiyorsanız değer Kl olmalıdır. Belgeler olayların çoğunu açmak için KEA dizesini önerir; bu dize m, n, o ve c dışındaki tüm olayları kapsar. Tablodaki a harfi, Redis 8.8 ile gelen Array veri tipinin komutlarına karşılık gelir; Array tipi için Array veri tipi yazımıza bakın.

bash
$ redis-cli config set notify-keyspace-events KEA

CONFIG SET ile yapılan değişiklik hemen, bir sonraki komuttan itibaren geçerli olur, ama yalnızca sunucunun başlatıldığı redis.conf dosyasını kendiliğinden değiştirmez. Dosyayı çalışan yapılandırmaya göre güncellemek için CONFIG REWRITE komutu vardır; bu adım CONFIG GET, SET ve REWRITE yazımızda anlatılıyor.

Bazı harfler daha yenidir ve eski sunucularda bulunmaz. Belgelerin geçmiş notlarına göre key miss olayları Redis 6.0, new olayı 7.0 ile eklendi. Redis 8.2 sürüm notları ise overwritten ve type_changed olaylarını yenilik olarak listeler. Bu olaylara dayanan bir tasarım yapacaksanız sunucunuzun sürümünü INFO server ile kontrol edin.

Hangi komut hangi olayı üretir?

Hangi komut hangi olayı üretir? DEL, silinen her anahtar için ayrı bir del olayı üretir., EXPIRE ve türevleri (PEXPIRE, EXPIREAT, PEXPIREAT) pozitif bir süreyle veya..., SET ve...

Belgeler komut başına üretilen olayların uzun bir listesini verir. Tasarımınızı en çok etkileyecek kurallar şunlardır:

  • DEL, silinen her anahtar için ayrı bir del olayı üretir.
  • EXPIRE ve türevleri (PEXPIRE, EXPIREAT, PEXPIREAT) pozitif bir süreyle veya gelecekteki bir zamanla çağrılınca expire olayı üretir. Negatif süre ya da geçmiş bir zaman verilirse anahtar silinir ve yalnızca del olayı üretilir.
  • SET ve türevleri (SETEX, SETNX, GETSET) set olayı üretir; SETEX ayrıca expire olayı da üretir. MSET her anahtar için ayrı bir set olayı üretir.
  • INCR, DECR, INCRBY ve DECRBY komutlarının hepsi incrby olayı üretir.
  • LPUSH ve RPUSH birden çok elemanla çağrılsa bile tek bir lpush veya rpush olayı üretir; SADD ve ZADD de öyle.
  • Bir yapıdan son eleman çıkarılıp anahtar boşaldığında (LPOP, SREM, HDEL, ZREM vb.) ek olarak del olayı gelir.
  • RENAME iki olay üretir: kaynak anahtar için rename_from, hedef anahtar için rename_to.
  • LMOVE ve BLMOVE bir lpush/rpush ve bir lpop/rpop olayı üretir; push olayının pop olayından önce geleceği garanti edilir.
  • HSET, HSETNX ve HMSET tek bir hset olayı üretir; HEXPIRE ve türevleri ile alanların süresi dolması hexpired olayı üretir.
  • Süresi dolan her anahtar için expired, maxmemory politikası nedeniyle çıkarılan her anahtar için evicted olayı üretilir.

Listenin altındaki kural en çok gözden kaçanıdır: komutlar yalnızca hedef anahtarı gerçekten değiştirdiklerinde olay üretir. Örneğin bir kümeden var olmayan bir elemanı silmeye çalışan SREM anahtarın değerini değiştirmediği için hiçbir olay oluşturmaz. Belirli bir komutun ne ürettiğinden emin değilseniz belgelerin önerisi kendiniz izlemektir:

bash
$ redis-cli config set notify-keyspace-events KEA
$ redis-cli --csv psubscribe '__key*__:*'
Reading messages... (press Ctrl-C to quit)
"psubscribe","__key*__:*",1

Ardından başka bir terminalden komut gönderdiğinizde olaylar akmaya başlar. Belgedeki örnekte foo anahtarına yapılan bir SET şu iki satırı üretir:

text
"pmessage","__key*__:*","__keyspace@0__:foo","set"
"pmessage","__key*__:*","__keyevent@0__:set","foo"

Bu satırlarda Pub/Sub yazısında anlattığımız pmessage biçimini görürsünüz: eşleşen kalıp, kanal adı ve mesaj. --csv seçeneği çıktıyı virgülle ayrılmış satırlara çevirerek okumayı kolaylaştırır.

expired olayı ne zaman gelir?

Süreli anahtarları kullanan çoğu kişi expired olayını bir zamanlayıcı gibi kullanmayı düşünür. Belgeler burada önemli bir uyarı yapar. Redis süresi dolan anahtarları iki yolla siler: bir komut anahtara eriştiğinde süresinin dolduğunu fark ederek ve erişilmeyen anahtarları da toplayabilmek için arka planda adım adım süresi dolmuş anahtar arayan bir sistemle. expired olayı bu iki sistemden biri anahtarı bulup sildiği anda üretilir; TTL değerinin sıfıra ulaştığı anda değil.

Sonuç olarak, anahtara sürekli erişen bir komut yoksa ve TTL'li çok sayıda anahtar varsa, TTL'nin sıfıra indiği an ile expired olayının üretildiği an arasında belirgin bir gecikme olabilir. Olayı "süre doldu, şimdi işlem yap" tetikleyicisi olarak kullanacaksanız bu gecikmeyi kabul edilebilir bulduğunuzdan emin olun. Süre yönetimi ve pasif/aktif silme için EXPIRE ve TTL yazımıza, bellek nedeniyle çıkarma ve evicted olayının arkasındaki politikalar için eviction yazımıza bakın.

Cluster ortamında bildirimler

Redis Cluster'ın her düğümü yalnızca kendi sorumlu olduğu anahtar alt kümesi için olay üretir. Belgelerin altını çizdiği fark şudur: cluster içindeki normal Pub/Sub iletişiminin aksine bu bildirimler tüm düğümlere yayılmaz, düğüme özgüdür. Cluster'ın tüm keyspace olaylarını almak istiyorsanız istemcinizin her düğüme ayrı ayrı abone olması gerekir. Cluster yapısı için Redis Cluster yazımıza bakın.

Hash alanları için subkey bildirimleri (Redis 8.8)

Hash alanları için subkey bildirimleri (Redis 8.8): __subkeyspace@__:, __subkeyevent@__:, __subkeyspaceitem@__: ve satır sonu ile, __subkeyspaceevent@__:|

Standart bildirimlerde bir hash alanı HSET, HDEL ya da HEXPIRE ile değiştiğinde abone yalnızca anahtar adını ve olay türünü öğrenir, hangi alanların etkilendiğini öğrenemez. Redis 8.8 ile gelen subkey bildirimleri bu boşluğu doldurur: mesaj, etkilenen alan adlarını da taşır. Bu özellik Redis 8.8 ve sonrasını gerektirir. Belgelere göre şu an yalnızca hash komutları desteklenir; diğer veri tipleri için destek sonraki sürümlere planlanmıştır.

Subkey bildirimleri standart keyspace ve keyevent kanallarından bağımsızdır: birini açmak diğerini açmaz. Dört yeni kanal türü vardır ve her biri farklı bir abonelik biçimine uygundur:

Kanal biçimiMesaj içeriğiNe zaman kullanılır
__subkeyspace@<db>__:<key>olay ve alan adlarıBelirli bir anahtarın alanlarını izlemek
__subkeyevent@<db>__:<event>anahtar adı ve alan adlarıBelirli bir olay türünü izlemek
__subkeyspaceitem@<db>__:<key> ve satır sonu ile <subkey>olayBelirli bir anahtar ve alan çiftini izlemek
__subkeyspaceevent@<db>__:<event>|<key>alan adlarıBelirli bir olay ve anahtar çiftini izlemek

Mesajlardaki alan adları <uzunluk>:<alan> biçiminde uzunluk ön ekiyle kodlanır; böylece ayraç karakteri içeren alan adları da güvenle taşınır. Belgeler birkaç güvenlik kuralı da tanımlar: adında | geçen olaylar ayrıştırma belirsizliği olmasın diye __subkeyspace ve __subkeyspaceevent kanallarına gönderilmez; adında satır sonu karakteri bulunan anahtarlar __subkeyspaceitem kanalına gönderilmez, çünkü satır sonu anahtar ile alan arasındaki ayraçtır; subkey olayları da yalnızca en az bir alan etkilendiyse yayımlanır.

Yapılandırma yine notify-keyspace-events ile yapılır ve dört yeni harf eklenmiştir: S subkeyspace, T subkeyevent, I subkeyspaceitem, V subkeyspaceevent kanallarını açar; h harfi hash komutlarını belirtir. Bu harfler K, E gibi anahtar düzeyindeki harflerden bağımsızdır ve istediğiniz bileşimi kullanabilirsiniz:

bash
$ redis-cli config set notify-keyspace-events ST
$ redis-cli --csv psubscribe '__subkey*'

Dört kanal türünün hepsini açmak için değer STIV olur. Subkey bildirimi üreten komutlar arasında HSET ve HMSET (ayarlanan tüm alanlar), HSETNX (yalnızca alan ayarlandıysa), HDEL, HINCRBY, HINCRBYFLOAT, HEXPIRE ailesi, HPERSIST, HGETDEL, HGETEX ve HSETEX bulunur; aktif ya da tembel biçimde süresi dolan alanlar ise tek bir hexpired bildiriminde toplu olarak gelir. Hash alanı süreleri için HEXPIRE yazımıza, hash komutları için HSET ve HGET yazımıza bakın.

Küçük bir uygulama: süresi dolan oturumları izlemek

Diyelim ki oturum anahtarlarınızı oturum: ön ekiyle ve bir TTL ile tutuyorsunuz ve bir oturum düştüğünde bir denetim kaydı yazmak istiyorsunuz. Burada keyevent kanalı uygundur, çünkü soru "hangi anahtarın süresi doldu?" sorusudur. Yalnızca keyevent türünü ve expired olaylarını açmak yeterlidir, yani Ex:

bash
$ redis-cli config set notify-keyspace-events Ex
$ redis-cli --csv subscribe __keyevent@0__:expired

Bu kanala gelen her mesajın içeriği, süresi dolup silinen anahtarın adıdır. Uygulamanız bu adı alıp oturum: ile başlayıp başlamadığına bakarak işlem yapabilir. Tasarımı yaparken iki kuralı aklınızda tutun: olay TTL'nin sıfıra indiği anda değil, Redis anahtarı sildiğinde gelir; abone bağlı değilken düşen oturumların olayları kaybolur. Denetim kaydının eksiksiz olması gerekiyorsa uygulamanız ayrıca kalıcı bir kayıt tutmalıdır. Tek bir veritabanı kullanmıyorsanız kanal adındaki @0 kısmını kendi veritabanı numaranızla değiştirin.

Sık yapılan hatalar

  • Dizeye K veya E koymamak: örneğin yalnızca x vermek hiçbir olay üretmez.
  • A sınıfının her şeyi kapsadığını sanmak: m, n, o ve c olayları A içinde değildir, ayrıca yazılmalıdır.
  • expired olayını kesin zamanlı bir tetikleyici sanmak: olay silme anında gelir ve gecikebilir.
  • Cluster'da tek düğüme abone olmak: bildirimler düğüme özgüdür, tüm düğümlere abone olun.
  • Değişiklik yapmayan komutlardan olay beklemek: var olmayan elemanı silen SREM gibi komutlar olay üretmez.
  • CONFIG SET ile açılan ayarın yeniden başlatmada kalacağını varsaymak: kalıcılık için redis.conf'a yazın.
  • Subkey bildirimlerini açınca standart bildirimlerin de açıldığını sanmak: iki sistem bağımsızdır.

Sık Sorulan Sorular

Keyspace notifications performansı etkiler mi?

Belgelere göre özellik biraz CPU harcadığı için varsayılan olarak kapalıdır. Yalnızca ihtiyaç duyduğunuz olay sınıflarını açarak bu maliyeti sınırlayabilirsiniz.

Bir anahtarın hangi alanının değiştiğini öğrenebilir miyim?

Standart bildirimlerle hayır, yalnızca anahtar adı ve olay türü gelir. Redis 8.8 ve sonrasında hash anahtarları için subkey bildirimleri etkilenen alan adlarını da verir.

Hangi veritabanının olaylarını alırım?

Kanal adındaki @ işaretinden sonraki sayı veritabanı numarasıdır; __keyspace@0__ 0 numaralı veritabanının olaylarını taşır. Birden çok veritabanı için kalıp aboneliği kullanabilirsiniz.

Olaylar kaybolabilir mi?

Evet. Bildirimler Pub/Sub ile iletilir ve Pub/Sub mesajları saklamaz; bağlantısı kopan abone aradaki olayları alamaz.

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 · Redis Pub/Sub · Redis EXPIRE ve TTL · Hash alan süresi · maxmemory ve eviction · CONFIG GET ve SET