介绍
键空间通知可以让客户端实时监听Redis键和值的变化,比如删除、新增、修改重命名等
配置
因为开启键空间通知功能需要消耗一些CPU,所以默认清空下该功能是关闭的,可以通过修改redis.conf文件,windows版本是redis.windows.conf文件,或者使用config set 命令来临时开启或关闭键空间通知功能,但使用命令的方式如果Redis重启了将会被还原。
- 当notify-keyspace-events选项为空字符串时,该功能关闭
- 当notify-keyspace-events选项不为空字符串时,该功能开启
- 当notify-keyspace-events选项为KEA时,开启所有配置
- 要注意大小写
notify-keyspace-events可以是以下任意组合
字符 | 发送的通知 |
---|---|
K | 键空间通知,所有通知以 __keyspace@<db>__ 为前缀 |
E | 键事件通知,所有通知以 __keyevent@<db>__ 为前缀 |
g | del、expire、rename 等类型无关的通用命令的通知 |
$ | string命令的通知 |
l | list命令的通知 |
s | set命令的通知 |
h | hash命令的通知 |
z | zset命令的通知 |
x | 过期事件:每当有过期键被删除时发送 |
e | 驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送 |
A | 参数 g$lshzxe 的别名 |
注:参数至少要有一个k或者E,否则不会有任何通知,将参数设为AKE表示所有类型的通知
各种通知的产生
- DEL key [key …] 命令为每个被删除的键产生一个 del 通知。
- RENAME key newkey 产生两个通知:为来源键(source key)产生一个 rename_from 通知,并为目标键(destination key)产生一个 rename_to 通知。
- EXPIRE key seconds 和 EXPIREAT key timestamp 在键被正确设置过期时间时产生一个 expire 通知。当 EXPIREAT key timestamp 设置的时间已经过期,或者 EXPIRE key seconds 传入的时间为负数值时,键被删除,并产生一个 del 通知。
- SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern …]] [ASC | DESC] [ALPHA] [STORE destination] 在命令带有 STORE 参数时产生一个 sortstore 事件。如果 STORE 指示的用于保存排序结果的键已经存在,那么程序还会发送一个 del 事件。
- SET key value [EX seconds] [PX milliseconds] [NX|XX] 以及它的所有变种(SETEX key seconds value 、 SETNX key value 和 GETSET key value)都产生 set 通知。其中 SETEX key seconds value 还会产生 expire 通知。
- MSET key value [key value …] 为每个键产生一个 set 通知。
- SETRANGE key offset value 产生一个 setrange 通知。
- INCR key 、 DECR key 、 INCRBY key increment 和 DECRBY key decrement 都产生 incrby 通知。
- INCRBYFLOAT key increment 产生 incrbyfloat 通知。
- APPEND key value 产生 append 通知。
- LPUSH key value [value …] 和 LPUSHX key value 都产生单个 lpush 通知,即使有多个输入元素时,也是如此。
- RPUSH key value [value …] 和 RPUSHX key value 都产生单个 rpush 通知,即使有多个输入元素时,也是如此。
- RPOP key 产生 rpop 通知。如果被弹出的元素是列表的最后一个元素,那么还会产生一个 del 通知。
- LPOP key 产生 lpop 通知。如果被弹出的元素是列表的最后一个元素,那么还会产生一个 del 通知。
- LINSERT key BEFORE|AFTER pivot value 产生一个 linsert 通知。
- LSET key index value 产生一个 lset 通知。
- LTRIM key start stop 产生一个 ltrim 通知。如果 LTRIM key start stop 执行之后,列表键被清空,那么还会产生一个 del 通知。
- RPOPLPUSH source destination 和 BRPOPLPUSH source destination timeout 产生一个 rpop 通知,以及一个 lpush 通知。两个命令都会保证 rpop 的通知在 lpush 的通知之前分发。如果从键弹出元素之后,被弹出的列表键被清空,那么还会产生一个 del 通知。
- HSET hash field value 、 HSETNX hash field value 和 HMSET 都只产生一个 hset 通知。
- HINCRBY 产生一个 hincrby 通知。
- HINCRBYFLOAT 产生一个 hincrbyfloat 通知。
- HDEL 产生一个 hdel 通知。如果执行 HDEL 之后,哈希键被清空,那么还会产生一个 del 通知。
- SADD key member [member …] 产生一个 sadd 通知,即使有多个输入元素时,也是如此。
- SREM key member [member …] 产生一个 srem 通知,如果执行 SREM key member [member …] 之后,集合键被清空,那么还会产生一个 del 通知。
- SMOVE source destination member 为来源键(source key)产生一个 srem 通知,并为目标键(destination key)产生一个 sadd 事件。
- SPOP key 产生一个 spop 事件。如果执行 SPOP key 之后,集合键被清空,那么还会产生一个 del 通知。
- SINTERSTORE destination key [key …] 、 SUNIONSTORE destination key [key …] 和 SDIFFSTORE destination key [key …] 分别产生 sinterstore 、 sunionostore 和 sdiffstore 三种通知。如果用于保存结果的键已经存在,那么还会产生一个 del 通知。
- ZINCRBY key increment member 产生一个 zincr 通知。(译注:非对称,请注意。)
- ZADD key score member [[score member] [score member] …] 产生一个 zadd 通知,即使有多个输入元素时,也是如此。
- ZREM key member [member …] 产生一个 zrem 通知,即使有多个输入元素时,也是如此。如果执行 ZREM key member [member …] 之后,有序集合键被清空,那么还会产生一个 del 通知。
- ZREMRANGEBYSCORE key min max 产生一个 zrembyscore 通知。(译注:非对称,请注意。)如果用于保存结果的键已经存在,那么还会产生一个 del 通知。
- ZREMRANGEBYRANK key start stop 产生一个 zrembyrank 通知。(译注:非对称,请注意。)如果用于保存结果的键已经存在,那么还会产生一个 del 通知。
- ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX] 和 ZUNIONSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX] 分别产生 zinterstore 和 zunionstore 两种通知。如果用于保存结果的键已经存在,那么还会产生一个 del 通知。
所有命令只有在key真的被改动之后,才会产生通知,比如del key,如果这个key不存在那么就不会产生通知。
使用Redis-cli来模拟键空间通知
可以先临时更改notify-keyspace-events的选项
127.0.0.1:6379> config set notify-keyspace-events Ex
然后开始订阅
127.0.0.1:6379> psubscribe '__key*__:*'
psubscribe说明请参考psubscribe命令详解
回车之后我们可以看到如下东西
127.0.0.1:6379> psubscribe '__key*__:*'
Reading messages... (press Ctrl-C to quit) #按ctrl+c会退出redis-cli.exe
1) "psubscribe" #返回值的类型,显示订阅成功
2) "__key*__:*" #订阅的模式
3) (integer) 1 #目前已订阅成功的数量
然后我们再开一个客户端然后设置一个key
127.0.0.1:6379> set ab a
这边我们就会收到这样的内容
1) "pmessage" #返回值的类型
2) "__key*__:*" #订阅的模式
3) "__keyevent@0__:set" #订阅的通知类型
4) "ab" #key名
如果是Hash、list、set和zset的话会增加一个key空间通知
1) "pmessage" #返回值的类型
2) "__key*__:*" #订阅的模式
3) "__keyspace@0__:key" #键空间通知+key名
4) "hset" #通知类型
5) "pmessage" #返回值的类型
6) "__key*__:*" #订阅的模式
7) "__keyevent@0__:hset" #键事件通知+几库+通知类型
8) "key" #key名
如此可以得出,键空间通知是指针对hash、list、set和zset的时候才会产生,而针对String不会产生,所以想要订阅hash、list、set和zset的时候,配置一定要加上K选项。
整合SpringBoot来完成键空间通知
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、配置好yml
spring:
redis:
host: localhost #主机
port: 6379 #端口号
password: #密码
jedis:
pool:
max-active: 8
max-wait: -1
max-idle: 500
min-idle: 0
lettuce:
shutdown-timeout: 0
3、增加监听类
下面的topic是订阅set通知,如果还想要订阅其他的请再写一个类,并修改订阅的通知类型
import lombok.Data;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.stereotype.Component;
@Component
@Data
public class RedisUpdateAndAddListener implements MessageListener {
//监听的主题
private final PatternTopic topic = new PatternTopic("__keyevent@*__:set");
@Override
public void onMessage(Message message, byte[] pattern){
String topic = new String(pattern);
String msg = new String(message.getBody());
System.out.println("收到key更新或修改,消息主题是:"+ topic+",消息内容是:"+msg);
}
}
4、在RedisConf文件增加以下代码
@Autowired
private RedisUpdateAndAddListener redisUpdateAndAddListener;
@Bean
RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
//监听所有的key的set事件
container.addMessageListener(redisUpdateAndAddListener, redisUpdateAndAddListener.getTopic());
return container;
}
到此则已经完成了整合SpringBoot。