원문: https://redis.io/topics/notifications
IMPORTANT Keyspace notifications is a feature available since 2.8.0
키 스페이스 노티피케이션(Keyspace notifications)은 클라이언트가 레디스의 데이터 셋이 어떠한 형태로 영향을 받은 이벤트를 수신하기 위해서 Pub/Sub
채널을 구독하게 하는 것이다.
수신할 수 있는 이벤트의 예는 다음과 같다.
이벤트는 레디스의 일반적인 Pub/Sub 계층을 이용해서 전달되며, 그렇기 때문에 Pub/Sub을 구현하는 클라이언트는 변경없이 이 기능을 이용하는 것이 가능하다.
레디스 Pub/Sub은 fire and forget이기 때문에, 만약 당신의 어플리케이션이 이벤트에 대한 신뢰할 수 있는 통지(reliable notification)에 대한 요구가 있다면, 현재는 이 기능을 이용할 방법이 없을 것이다. 당신의 Pub/Sub 클라이언트가 한 번 연결을 끊고 나서 다시 연결을 맺을 때, 클라이언트는 접속이 끊겼던 시간 동안에 전달된 모든 이벤트들을 잃게 된다.
향후에는 좀 더 신뢰할 수 있는 이벤트의 딜리버리가 가능하도록 하려는 계획이 있지만, 아마도 이것은 좀 더 일반적인 수준으로 다루어질 것이다. Pub/Sub 그 자체가 신뢰성을 갖게 되는 것이나, 또는 루아(Lua) 스크립트가 Pub/Sub 이벤트를 리스트로 푸시하는 것과 같은 오퍼레이션을 수행하기 위해 Pub/Sub 메시지를 가로챌 수 있도록 하는 것 등이다.
키 스페이스 노티피케이션은 레디스 데이터 스페이스에 영향을 주는 모든 오퍼레이션마다 두 가지의 구별되는 형태의 이벤트를 보냄으로써 구현된다. 예를 들어, 데이터베이스 0 안에 있는 mykey
라고 이름이 붙여진 키에 대한 DEL
오퍼레이션은 두 가지 메시지를 발생시킬 것이고, 이는 다음의 두 PUBLISH
커맨드와 정확히 동일하다.
PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey
어떻게 우리는 한 채널로부터 mykey
에 대한 이벤트를 모두 수신할 수 있는지, 그리고 어떻게 또 다른 채널로부터 del
오퍼레이션의 대상이 되는 모든 키에 대한 정보를 얻을 수 있는지를 쉽게 알 수 있을 것이다.
채널 내에서 keyspace
프리픽스를 가진 첫 번째 종류의 이벤트는 키-스페이스 노티피케이션 (key-space notification) 이라고 부른다. 반면에 keyevent
프리픽스를 가진 두 번째 종류의 이벤트는 키-이벤트 노티피케이션 (key-event notification) 이라고 부른다.
위의 예에서, del
이벤트는 mykey
에 대해서 발생되었는데, 이에 대해 일어난 일은 다음과 같다.
우리가 관심이 있는 이벤트의 일부만을 전달받기 위해, 오직 하나의 종류의 노티피케이션만 활성화하는 것이 가능하다.
기본적으로 키 스페이스 이벤트 노티피케이션은 비활성화되어 있는데, 이 기능은 눈에 띌 만큼은 아니지만 CPU 자원을 일부 사용하기 때문이다. 노티피케이션은 redis.conf의 notify-keyspace-events
옵션을 사용하거나 CONFIG SET을 통해서 활성화될 수 있다.
이 파라미터를 빈 문자열로 설정하는 것은 노티피케이션을 비활성화한다. 이 기능을 활성화하기 위해서 비어있지 않은 문자열이 사용되는데, 이 문자열은 여러 문자들로 구성되며, 모든 문자들은 다음의 테이블에 따라 특별한 의미를 가진다:
K Keyspace events, published with __keyspace@<db>__ prefix.
E Keyevent events, published with __keyevent@<db>__ prefix.
g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
$ String commands
l List commands
s Set commands
h Hash commands
z Sorted set commands
t Stream commands
x Expired events (events generated every time a key expires)
e Evicted events (events generated when a key is evicted for maxmemory)
A Alias for g$lshztxe, so that the "AKE" string means all the events.
최소한 K
나 E
는 문자열에 지정해야하며, 그렇지 않으면 나머지 문자열에 관계없이 어떠한 이벤트도 전달되지 않는다.
예를 들어, 그저 LIST
에 대해서만 키 스페이스 이벤트를 활성화하려면, 설정 값은 Kl
등으로 지정해야만 한다.
KEA
는 가능한 모든 이벤트를 활성화시키기 위해서 사용될 수 있다.
각각의 커맨드는 다음의 목록에 따라 각기 다른 종류의 이벤트를 발생시킨다.
DEL
은 모든 삭제되는 키에 대해서 del
이벤트를 발생시킨다.RENAME
은 두 가지 이벤트를 발생시키는데, 하나는 원본 키에 대한 rename_from
이벤트이고, 다른 하나는 대상 키에 대한 rename_to
이벤트이다.EXPIRE
는 키에 대해서 만료 시간(expire)가 설정될 때 expire
이벤트를 발생시킨거나, 키에 타임아웃이 설정되고, 그 결과로 키가 삭제될 때마다 expired
이벤트가 발생하게 된다. (좀 더 많은 정보는 EXPIRE
문서를 참고할 것).SORT
는 새로운 키에 저장하기 위해 STORE
옵션이 사용될 때, sortstore
아벤트가 발생시킨다. 만약, 정렬한 결과 리스트가 비어있고, STORE
옵션이 사용된다면, 그리고 저장하려는 키가 이미 존재한다면, 그 키는 삭제될 것이고, 따라서 이 조건에서는 del
이벤트가 발생한다.SET
과 그리고 이와 비슷한 커맨드들(SETEX
, SETNX
,GETSET
)은 set
이벤트를 발생시킨다. 그리고 SETEX
는 expire
이벤트 또한 발생시킨다.MSET
은 각각의 키별로 set
이벤트를 발생시킨다.SETRANGE
는 setrange
이벤트를 발생시킨다.INCR
, DECR
, INCRBY
, DECRBY
커맨드들은 모두 incrby
이벤트를 발생시킨다.INCRBYFLOAT
는 incrbyfloat
이벤트를 발생시킨다.APPEND
는 append
이벤트를 발생시킨다.LPUSH
와 LPUSHX
는 단일 lpush
이벤트를 발생시키는데, 가변적인 인자에 대해서도 마찬가지이다.LPUSH
와 LPUSHX
는 단일 rpush
이벤트를 발생시키는데, 가변적인 인자에 대해서도 마찬가지이다.RPOP
은 rpop
이벤트를 발생시키다. 만약 리스트 내의 마지막 엘리먼트가 pop되는 경우에는, 추가적으로 del
이벤트가 발생된다.LPOP
은 lpop
이벤트를 발생시키다. 만약 리스트 내의 마지막 엘리먼트가 pop되는 경우에는, 추가적으로 del
이벤트가 발생된다.LINSERT
는 linsert
이벤트를 발생시킨다.LSET
는 lset
이벤트를 발생시킨다.LREM
는 lrem
이벤트를 발생시킨다. 만약 결과 리스트가 빈 값이고, 키가 삭제된다면 추가적으로 del
이벤트를 발생된다.LTRIM
는 ltrim
이벤트를 발생시킨다. 만약 결과 리스트가 빈 값이고, 키가 삭제된다면 추가적으로 del
이벤트를 발생된다.RPOPLPUSH
와 BRPOPLPUSH
는 rpop
이벤트와 lpush
이벤트를 발생시킨다. 두 가지의 경우 순서는 보장된다. (lpush
이벤트가 항상 rpop
이벤트의 이후에 전달된다.) 추가적으로 del
이벤트가 발생하는데, 만약 결과 리스트의 길이가 0이고, 키가 삭제된다면, 추가적으로 del
이벤트가 발생된다.HSET
, HSETNX
그리고 HMSET
모두 단일 hset
이벤트를 발생시킨다.HINCRBY
는 hincrby
이벤트를 발생시킨다.HINCRBYFLOAT
는 hincrbyfloat
이벤트를 발생시킨다.HDEL
은 단일 hdel
이벤트를 발생시키고, 만약 결과 해시가 빈 값이고, 키가 삭제된다면 추가적으로 del
이벤트를 발생시킨다.SADD
는 단일 sadd
이벤트를 발생시키는데, 가변적인 인자에 대해서도 마찬가지이다.SREM
은 단일 srem
이벤트를 발생시킨다. 만약, 결과 셋이 빈 값이고, 키가 삭제된다면 추가적으로 del
이벤트가 발생된다.SMOVE
는 원본 키에 대해서는 srem
이벤트를 발생시키고, 대상 키에 대해서는 sadd
이벤트를 발생시킨다.SPOP
은 spop
이벤트를 발생시킨다. 만약 결과 셋이 빈 값이고, 키가 삭제된다면 del
이벤트가 발생된다.SINTERSTORE
, SUNIONSTORE
, SDIFFSTORE
는 sinterstore
, sunionstore
, sdiffstore
이벤트를 각각 발생시킨다. 결과 셋이 비어있는 경우에, 그리고 저장하려는 키가 이미 존재한다면, 키가 삭제되기 때문에 del
이벤트가 발생한다.ZINCR
는 zincr
이벤트를 발생시킨다.ZADD
는 여러 엘리먼트가 추가되더라도 단일 zadd
이벤트를 발생시킨다.ZREM
은 여러 엘리먼트가 삭제되더라도 단일 zrem
이벤트를 발생시킨다. 결과 셋이 비어있고, 키가 삭제된다면, 추가적으로 del
이벤트가 발생된다.ZREMBYSCORE
는 단일 zrembyscore
이벤트를 발생시킨다. 결과 셋이 비어있고, 키가 삭제된다면, 추가적으로 del
이벤트가 발생된다.ZREMBYRANK
는 단일 zrembyrank
이벤트를 발생시킨다. 결과 셋이 비어있고, 키가 삭제된다면, 추가적으로 del
이벤트가 발생된다.ZINTERSTORE
와 ZUNIONSTORE
은 각각 zinterstore
와 zunionstore
이벤트를 발생시킨다. 결과 셋이 비어 있고, 저장하려는 키가 이미 존재하고 있다면, 키가 삭제되기 때문에 del
이벤트가 발생한다.XADD
는 xadd
이벤트를 발생시키고, MAXLEN
서브커맨드가 함께 사용될 때에는 xtrim
이 뒤어어 발생할 수 있다.XDEL
은 여러 엔트리가 삭제되더라도 단일 xdel
이벤트를 발생시킨다.XGROUP CREATE
은 xgroup-create
이벤트를 발생시킨다.XGROUP DELCONSUMER
은 xgroup-delconsumer
이벤트를 발생시킨다.XGROUP DESTROY
generates an xgroup-destroy
event.XGROUP DESTROY
은 xgroup-destroy
이벤트를 발생시킨다.XGROUP SETID
은 xgroup-setid
이벤트를 발생시킨다.XSETID
은 xsetid
이벤트를 발생시킨다.XTRIM
은 xtrim
이벤트를 발생시킨다.expired
이벤트가 발생한다.maxmemory
정책의 결과로, 여유 메모리 확보를 위해 키가 데이터 셋으로부터 추출(eviction)될 때마나, evicted
이벤트가 발생한다.IMPORTANT 모든 커맨드는 대상 키가 실제로 변경된 경우에만 이벤트를 발생시킨다. 예를 들어, SREM
이 셋으로부터 존재하지 않는 엘리먼트를 삭제하는 것은 실제로 키의 값을 변경시키기 않기 때문에, 아무런 이벤트도 발생하지 않는다.
주어진 커맨드에 대해 이벤트가 어떻게 발생하는 지에 대해 의심스러운 경우에 가장 간단히 할 수 있는 것은, 직접 보는 것이다:
$ redis-cli config set notify-keyspace-events KEA
$ redis-cli --csv psubscribe '__key*__:*'
Reading messages... (press Ctrl-C to quit)
"psubscribe","__key*__:*",1
이 시점에서 커맨드를 레디스 서버로 보내기 위해 또 다른 터미널에서 redis-cli
를 사용하고, 발생되는 이벤트를 관찰한다:
"pmessage","__key*__:*","__keyspace@0__:foo","set"
"pmessage","__key*__:*","__keyevent@0__:set","foo"
...
TTL이 설정된 키들은 레디스에 의해 다음의 2가지 방법으로 만료된다.
expired
이벤트는 위의 시스템 중 하나에 의해서 키로 접근이 발생하고, 만료된 사실이 발견되었을 때 발생한다. 그 결과, 레디스 서버가 키의 TTL이 0에 도달한 시점에 expired
이벤트를 발생시키는 것은 보장되지 않는다.
만약 특정 키를 대상으로하는 커맨드가 계속해서 없고, TTL이 설정된 키가 매우 많다면, 키의 TTL이 0이 된 시간과 expired
이벤트가 발생한 시간 사이에는 상당한 딜레이가 있을 수 있다.
기본적으로 expired
이벤트는 레디스 서버가 키를 삭제할 때 발생되는 이벤트이고, 이론적으로 TTL이 0으로 도달했을 때 발생하지는 않는다.
많이 도움 받았습니다. 감사합니다!