redis的数据库通知(notify-keyspace-events)
共分为两类:一类是键空间通知 另一类是键事件通知
概述
数据库通知是redis在2.8之后新增的功能,让客户端可以已发布/订阅模式来获取数据库中键的变化以及某事件的发生
- 首先要知道这个发送通知的操作是占内存的,所以默认的关闭的,需要我们手动的在redis.conf里面进行开启
- 如何开启:
- 进入redis安装地址的/redis/etc文件下,vim redis.conf
- 找到notify-keyspace-events,默认为“”,这里需要进行配置,配置完就开启了
- K Keyspace events, published with keyspace@ prefix.
E Keyevent events, published with keyevent@ 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
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$lshzxe, so that the “AKE” string means all the events. - K和E是必须要选一个配的,不行就配置AKE,表示所有的事件和键变化都会发送两条通知
开启后:
开启后能接收到的类型只有两种:keyspace和keyevent
前者为事件的具体操作,后者为事件影响的键名
- 数据库0中删除一个叫mykey的键 127.0.0.1:6379> del mykey
- 数据库0会发布下面两条信息:
- public keyspace@0:mykey del (键空间信息,mykey键被删了)
- public keyevent@0:del mykey (事件空间信息,执行了删除事件,删除了mykey)
redis发布后我们如何接受呢
项目中配置了redis.conf,redisListenerConfig之后
编写个 RedisKeyExpirationListenerServer 类继 KeyExpirationEventMessageListener
然后实现他的doRegister方法和onMessage方法
主要就是doRegister里面你进行订阅的topic是啥
- 想要订阅键空间就是 __keyspace,具体哪个键就后面@再加上键的key,如user,key a,key b等等。
- 想要订阅键事件就是__keyevent,具体哪个事件就后面@再加上事件的操作,如del ,set ,expire等
如何接收实例:
我的需求是当设置的某个键过期的时候,我这边能接收到这个事件,所以这里我接收的是keyevent@0__:expired这个topic
- 监听类的doRegister和onmessage方法
- doregister就是监听keyevent(键事件通知)中的expired事件
- tring topic = “keyevent@“+database+”:expired”;
- onMessage就是获取到这个过期的键的详情,直接message.toString就可以获取到这个过期键的key(这里要注意,message里面获取不到该过期键的value)
- String expiredKey = message.toString();
@Override
protected void doRegister(RedisMessageListenerContainer listenerContainer) {
String topic = "__keyevent@"+database+"__:expired";
log.info("配置监听哪个频道:"+topic);
PatternTopic patternTopic = new PatternTopic(topic);
// 频道可以是多,多个传list
listenerContainer.addMessageListener(this,patternTopic);
}
@Override
public void onMessage(Message message, byte[] pattern) {
// 用户做自己的业务处理即可,注意message.toString()可以获取失效的key
String expiredKey = message.toString();
log.info("失效的key"+expiredKey);
if(expiredKey.contains(RedisContact.SERVERNAME)){
deal(expiredKey);
}