redis键空间通知

  1. 键空间

每个redis服务器默认有16个db,编号为0~15,db以字典的形式保存所有的键值对,这个字典就叫做键空间。redis操作set、get、del、flushdb、randomkey等,都是对键空间的操作,都会产生键空间通知。键空间通知是通过redis的发布订阅机制实现的,通过订阅键空间通知,可以对感兴趣的redis操作或者数据的变化进行监听。

当有操作时,redis会固定向两个channel: __keyspace@<db>__:<key>(键空间通知)和__keyevent@<db>__:<event>(键事件通知),订阅者可通过psubscribe __keyevent@*__:*订阅任意库的任意事件的消息。

  1. 配置

因为开启键空间通知功能需要消耗一些 CPU,所以在默认配置下, 该功能处于关闭状态。可以修改redis配置文件redis.conf开启或关闭键空间通知。

  • notify-keyspace-events 为空字符串时,键空间通知关闭
  • 当给notify-keyspace-events 设值时,表示键空间通知开启

notify-keyspace-events 相关配置如下:

字符 & 发送的通知

K & 键空间通知,所有通知以 `__keyspace@<db>__` 为前缀

E & 键事件通知,所有通知以 `__keyevent@<db>__` 为前缀

g & DEL 、 EXPIRE 、 RENAME 等类型无关的通用命令的通知

$ & 字符串命令的通知

l & 列表命令的通知

s & 集合命令的通知

h & 哈希命令的通知

z & 有序集合命令的通知

x & 过期事件:每当有过期键被删除时发送

e & 驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送

A & 参数 g$lshzxe 的别名,即all

输入的参数中至少要有一个 K 或者 E , 否则的话, 不管其余的参数是什么, 都不会有任何通知被分发。例如:notify-keyspace-events 配置为 EX时,当有键值对过期时,将发送通知,channel为__keyevent@0__:expired。当配置为KEA时,会发送所有操作的键空间通知和键事件通知。

  1. 命令演示

通过命令psubscribe __keyevent@*__:expired订阅所有库过期事件的通知

set键值对mykey, 并设置10s后过期

mykey过期后,收到消息通知

  1. Java代码实现

1)引入spring-data-redis依赖包

2)配置redis连接池和消息监听容器

<bean class="redis.clients.jedis.JedisPoolConfig" id="jedisPoolConfig">

<property name="maxIdle" value="50" />

<property name="maxTotal" value="500" />

<property name="maxWaitMillis" value="10000" />

<property name="testOnBorrow" value="true" />

<property name="timeBetweenEvictionRunsMillis" value="30000" />

<property name="numTestsPerEvictionRun" value="100" />

</bean>

<!-- 下面是配置模板方式 springData管理 redisTemplate -->

<!--jedisFactory-->

<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" id="jedisConnFactory">

<property name="poolConfig" ref="jedisPoolConfig"/>

<property name="hostName" value="139.129.241.130"/>

<property name="port" value="6379"/>

<property name="timeout" value="10000"/>

</bean>

<bean class="org.springframework.data.redis.core.RedisTemplate" id="redisTemplate">

<property name="connectionFactory" ref="jedisConnFactory"/>

<property name="keySerializer">

<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

</property>

<property name="valueSerializer">

<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>

</property>

</bean>

<bean id="messageListener" class="com.dubbo.service.impl.ExpiredKeyNotification">

<property name="redisTemplate" ref="redisTemplate"/>

</bean>

<!-- 配置监听者容器 -->

<bean id="redisContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer">

<property name="connectionFactory" ref="jedisConnFactory"/>

<property name="messageListeners">

<map>

<entry key-ref="messageListener">

<list>

<bean class="org.springframework.data.redis.listener.PatternTopic">

<constructor-arg value="__keyevent@*__:expired"/>

</bean>

</list>

</entry>

</map>

</property>

</bean>

3)实现消息监听接口

public class ExpiredKeyNotification implements MessageListener {

@Override

public void onMessage(Message message, byte[] bytes) {

System.out.println("收到消息");

byte[] body = message.getBody();

byte[] channel = message.getChannel();

//设置监听频道

String topic = new String(channel);

//key

String itemValue = new String(body);

System.out.println("频道topic:"+topic);

System.out.println("过期的键值对的K:"+itemValue);

}

}

4)当redis服务器有过期键时,就会发送通知

  1. 问题分析

1) 因为redis键空间通知是利用redis发布订阅机制实现的,因此不能作为一个可靠的通知,当客户端重启或宕机时,很有可能丢失消息。

2)使用redis键空间通知,需要先开启notify-keyspace-events 的配置,该功能比较消耗cpu,最好使用单独的redis服务器或集群。

3)过期通知的发送时间,因为redis删除过期键的方式有两个,一个是当键被访问时,会去检查是否过期;另一个是redis-server会渐近的检查并删除过期键。当过期键被发现并删除时,并且有订阅者正在监听对应的channel,会向该channel推送键过期通知。因此,redis不能保证过期键立即被删除,特别是当带有有效期的键值对较多时,可能会有明显的延迟。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值