一、概述
Redis键空间通知(keyspace notifications)是基于订阅/发布(Pub/Sub)机制。
二、事件类型
- keyspace事件
- keyevent事件
比如,在0号库,键myKey过期,会触发两个消息,等价于执行两个publish命令:
publish __keyspace@0__:myKey expired
publish __keyevent@0__:expired myKey
可以通过配置,使Redis仅发送某一类通知
三、配置
可以通过修改配置文件redis.conf
,或者通过config set
命令,设置notify-keyspace-events
选项,来启用或关闭该功能
该选项的值为空字符串时,该功能禁用,选项值为非空字符串时,启用该功能,非空字符串由特定的多个字符组成,每个字符表示不同的意义:
- K:keyspace事件,事件以
__keyspace@<db>__
为前缀进行发布 - E:keyevent事件,事件以
__keyevent@<db>__
为前缀进行发布 - g:一般性的,非特定类型的命令,比如del,expire,rename等
- $:字符串特定命令
- l:列表特定命令
- s:集合特定命令
- h:哈希特定命令
- z:有序集合特定命令
- x:过期事件,当某个键过期并删除时会产生该事件
- e:驱逐事件,当某个键因maxmemore策略而被删除时,产生该事件
- A:g$lshzxe的别名,因此”AKE”意味着所有事件
例如:
设置键过期,发送keyspace事件和keyevent事件通知
config set notify-keyspace-events "xKE"
四、命令
- DEL 命令为每个被删除的键产生一个 del 事件;
- RENAME 产生两个事件:为源键产生一个 rename_from 事件,并为目标键产生一个 rename_to 事件;
- EXPIRE命令,在设置键的过期时间时产生一个 expire事件;当键因过期而被删除时,产生一个 expired事件;
- MSET 命令,为每个键产生一个 set 事件;
五、命令行使用键空间通知
1.配置通知
设置键过期,发送keyspace事件和keyevent事件通知
config set notify-keyspace-events "xKE"
2.栗子
keyspace事件订阅端:
psubscribe __keyspace@0__:mykey
keyevent事件订阅端:
psubscribe __keyevent@0__:expired
发布端:
10s 后myKey过期
setex myKey 10 "zhang san"
3.结果
keyspace事件订阅端结果:
1) "pmessage"
2) "__keyspace@0__:myKey"
3) "__keyspace@0__:myKey"
4) "expired
keyevent事件订阅端结果:
1) "pmessage"
2) "__keyevent@0__:expired"
3) "__keyevent@0__:expired"
4) "myKey"
六、java使用键空间通知
pom 文件
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
1.配置通知
设置键过期,发送keyspace事件和keyevent事件通知
@Test
public void testConfigKeyspace() {
Jedis jedis = new Jedis("localhost");
jedis.configSet("notify-keyspace-events", "xKE");
}
2.栗子
回调类
public class Subscriber extends JedisPubSub {
@Override
public void onPMessage(String pattern, String channel, String message) {
System.out.println(String.format("onPMessage: pattern %s, channel %s, message %s", pattern, channel, message));
}
@Override
public void onPSubscribe(String pattern, int subscribedChannels) {
System.out.println(String.format("onPSubscribe: pattern %s, subscribedChannels %s", pattern, subscribedChannels));
}
@Override
public void onPUnsubscribe(String pattern, int subscribedChannels) {
System.out.println(String.format("onPUnsubscribe: pattern %s, subscribedChannels %s", pattern, subscribedChannels));
}
// 收到消息会调用
@Override
public void onMessage(String channel, String message) {
System.out.println(String.format("onMessage: channel %s, message %s", channel, message));
}
// 订阅了频道会调用
@Override
public void onSubscribe(String channel, int subscribedChannels) {
System.out.println(String.format("onSubscribe: channel %s, subscribedChannels %d",
channel, subscribedChannels));
}
// 取消订阅 会调用
@Override
public void onUnsubscribe(String channel, int subscribedChannels) {
System.out.println(String.format("onUnsubscribe: channel %s, subscribedChannels %d",
channel, subscribedChannels));
}
}
keyspace事件订阅端:
@Test
public void testPsubscribeKeyspace() {
Jedis jedis = new Jedis("localhost");
jedis.psubscribe(new Subscriber(), "__keyspace@0__:myKey");
}
keyevent事件订阅端:
@Test
public void testPsubscribeKeyevent() {
Jedis jedis = new Jedis("localhost");
jedis.psubscribe(new Subscriber(), "__keyevent@0__:expired");
}
发布端:
10s 后myKey过期
@Test
public void testExpire() {
Jedis jedis = new Jedis("localhost");
jedis.set("myKey", "zhang san");
jedis.expire("myKey", 10);
}
3.结果
keyspace事件订阅端结果:
onPSubscribe: pattern __keyspace@0__:myKey, subscribedChannels 1
onPMessage: pattern __keyspace@0__:myKey, channel __keyspace@0__:myKey, message expired
keyevent事件订阅端结果:
onPSubscribe: pattern __keyevent@0__:expired, subscribedChannels 1
onPMessage: pattern __keyevent@0__:expired, channel __keyevent@0__:expired, message myKey