Redis键空间通知

重要 键空间通知是2.8.0以后版本可用的一个特性。

特性概览

键空间通知允许客户端订阅Pub/Sub通道,以便接收对Redis数据集的某些方面影响的事件。

可以被接收的事件的例子:

  • 影响给定键的所有命令。
  • 接收一个LPUSH操作的所有键。
  • 在数据库0所有过期的键。

事件使用Redis的Pub/Sub层来传递,所以客户端可以使用这些特征实现Pub/Sub而不需要做修改。

因为Redis Pub/Sub是发射既忘(fire and forget),目前没有办法使用这个特征,如果你的应用需求是事件的可信通知的话,那是因为,如果你的Pub/Sub客户端失去连接,且稍后重连接时,所有的事件在重新连接时都丢失。

未来有计划允许更可靠的事件传递,不过这将很可能定位在更一般层级上的,要么是给Pub/Sub本身带来可靠性,要么是允许Lua脚本拦截Pub/Sub消息以执行诸如将事件推入列表这样的操作。

事件类型

键空间的通知通过为每个影响Redis数据空间的操作发送两种不同的事件类型实现。比如,一个DEL操作命中数据库0中名为mykey的键将触发传递2个消息,准确来说等于下面的两个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)
m     Key miss events (events generated when a key that doesn't exist is accessed)
A     Alias for "g$lshztxe", so that the "AKE" string means all the events except "m".

至少KE必须在字符串中出现,否则剩余的字符串中将不会有事件会被传递。

例如,为列表仅开启Key-space事件,这个配置参数必须设置为K1,等等。

字符串KEA可以用于开启每个可能的事件。

不同命令生成的事件

  • DEL 为每个被删除的键生成一个del事件。
  • RENAME 生成两个事件,一个是为源键生成rename_from事件,另一个是为目标键生成rename_to事件。
  • MOVE 生成两个时间,一个是为源键生成move_from时间,另一个是为目标键生成move_to事件。
  • COPY 生成一个copy_to事件。
  • MIGRATE 如果源键被移除,生成一个del事件。
  • RESTORE 为此键生成一个restore事件。
  • EXPIRE 和它所有的变体(PEXPIRE, EXPIREAT, PEXPIREAT)使用一个正的超时时间(或一个未来的时间戳)调用时,会生成一个expire事件。
  • SORTstore用于设置一个新的键时,生成一个sortstore事件。如果结果列表为空,并且STORE选项已经使用,并且有一个已经存在的键使用那个名字,那么结果就是那个键被删除,因此在这种情况下一个del事件被生成。
  • SET 和其所有的变种(SETEX, SETNX,GETSET)生成一个set事件。然而SETEX还会生成一个expire事件。
  • MSET 为每个键生成一个单独的set事件。
  • SETRANGE 生成一个setrange事件。
  • INCR, DECR, INCRBY, DECRBY 这些命令都生成incrby事件。
  • INCRBYFLOAT 生成一个incrbyfloat事件。
  • APPEND 生成一个append事件。
  • LPUSHLPUSHX 生成一个单独的lpush事件,即使在一个可变参数的情况下。
  • RPUSHRPUSHX 生成一个单独的rpush事件,即使在可变参数的情况下。
  • RPOP 生成一个rpop事件。如果因为列表中最后一个元素被弹出而导致这个键被删除时,会有一个额外的del事件生成。
  • LPOP 生成一个lpop事件。如果因为列表中最后一个元素被弹出而导致这个键被删除时,会有一个额外的del事件生成。
  • LINSERT 生成一个linsert事件。
  • LSET 生成一个lset事件。
  • LREM 生成一个 lrem 事件,如果结果列表为空且这个键被删除时,会有一个额外的del事件生成。
  • LTRIM 生成一个ltrim事件,如果结果列表为空且这个键被删除时,会有一个额外的del事件生成。
  • RPOPLPUSHBRPOPLPUSH 生成一个rpop事件和一个lpush事件。在这两种情况下顺序都是有保证的(lpush总是在rpop)。
  • LMOVEBLMOVE 生成一个lpop/rpop事件(取决于来向参数)和一个lpush/rpush事件(取决于去向参数)。在这两种情况下顺序都是有保障的(lpush/rpush事件总是在lpop/rpop事件之后传递)。当结果列表长度为0并且该键被移除后,会产生一个额外的del事件。
  • HSET, HSETNXHMSET 都生成一个hset事件。
  • HINCRBY生成一个hincrby事件。
  • HINCRBYFLOAT 生成一个hincrbyfloat 事件。
  • HDEL 生成一个单独的hdel事件,如果结果哈希为空且被移除的话,会生成一个额外的del事件。
  • SADD 生成一个单独的sadd事件,甚至在可变参的情形中。
  • SREM 生成一个srem事件,如果结果集为空且键被移除的话,会生成一个额外的del事件。
  • 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事件。
  • ZDIFFSTORE, ZINTERSTOREZUNIONSTORE 分别生成 zdiffstore, zinterstorezunionstore 事件。在特殊情况下,当结果有序集合为空,且键已经在存储结果中存在时,如果键被移除会生成一个del事件。
  • XADD 生成一个xadd事件,当和子命令MAXLEN一起使用时,可能会跟着一个xtrim事件。
  • XDEL 生成单个 xdel事件,即使当多个实体被删除时。
  • XGROUP CREATE 生成一个xgroup-create 事件。
  • XGROUP CREATECONSUMER 生成一个 xgroup-createconsumer 事件。
  • XGROUP DELCONSUMER 生成一个 xgroup-delconsumer 事件。
  • XGROUP DESTROY 生成一个 xgroup-destroy 事件。
  • XGROUP SETID 生成一个 xgroup-setid 事件。
  • XSETID 生成一个 xsetid 事件。
  • XTRIM 生成一个 xtrim 事件。
  • PERSIST 生成一个 persist 事件,如果键关联的过期时间被成功删除的话。
  • 每当一个关联了生存时间的键因为过期而被从数据集中删除时,一个expired事件生成了。
  • 每当出于maxmemory策略的结果,将一个键从数据集中回收从而释放内存的时候,一个evicted事件就会生成。

重要 所有的命令只在目标键真实改变时生成事件。比如,一个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发送命令到Redis服务端,并且观察事件的生成:

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

过期事件的时间线

Redis通过两种方式使与生存时间关联的键过期:

  • 当该键被一个命令访问,且被发现过期了。
  • 通过后台系统,以增量方式在后台查找过期的键,同时搜集那些从未被访问过的键。

当一个键被访问且被上面的系统之一发现过期后,产生一个expired事件,因此不能保证Redis服务器能够在键的生存时间到0时生成expired事件。

如果没有命令经常访问键,且有很多有TTL关联的键,在键的生存时间降低为0和生成expired事件的时间之间将会有一个较大的延迟。

基本上来讲,是当Redis服务器删除键时而并不是键的理论的生存时间到达为0时,生成expired事件。

集群中的事件

如上所述,每个Redis集群生成自己键空间的子集。可是,不像规则的Pub/Sub在集群中的通讯,事件通知不是广播到所有的节点。不同的是,键空间事件是节点特异性的。这意味着,为了接收集群的所有的键空间事件,客户端需要订阅每个节点。

History 记录

  • >= 6.0:增加了键丢失事件
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容