美文网首页
Redis键空间通知

Redis键空间通知

作者: 颍水书生 | 来源:发表于2021-03-14 23:14 被阅读0次

    重要 键空间通知是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:增加了键丢失事件

    相关文章

      网友评论

          本文标题:Redis键空间通知

          本文链接:https://www.haomeiwen.com/subject/xzqhcltx.html