Redis中的事件是通过订阅/发布(sub/pub)功能来实现的。在redis中,某个key的过期事件和该key的删除事件,是不一样的。
对于每个redis的数据库操作,redis都会生成一个对应的事件。这些事件,形似以“__keyevent@*”开头。详细内容可以在redis的配置文件的EVENT NOTIFICATION模块中看到。
其中,参数notify-keyspace-events,用来控制是否开启这些通知。如果想使用过期和删除事件,务必保证在redis的配置文件中,对该参数做出正确的配置并重启redis。
K:keyspace事件,事件以__keyspace@<db>__为前缀进行发布;
E:keyevent事件,事件以__keyevent@<db>__为前缀进行发布;
g:一般性的,非特定类型的命令,比如del,expire,rename等;
$:字符串特定命令;
l:列表特定命令;
s:集合特定命令;
h:哈希特定命令;
z:有序集合特定命令;
x:过期事件,当某个键过期并删除时会产生该事件;
e:驱逐事件,当某个键因maxmemore策略而被删除时,产生该事件;
A:g$lshzxe的别名,因此”AKE”意味着所有事件。
回到开始的问题,key的过期事件和key的删除事件,都是什么哪?
SUBSCRIBE __keyevent@0__:expired
SUBSCRIBE __keyevent@0__:del
redis中用expired和del来区分key是过期?还是被手动删除。
下面用springboot来示例下,这两个时间如何实现。
创建过期事件监听器类:
package com.***.***.listener;import org.springframework.beans.factory.annotation.Autowired;
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;import com.yinghui.adapter.service.ConsumeService;
import com.yinghui.common.constant.Constants;import lombok.Data;
import lombok.extern.slf4j.Slf4j;@Component
@Data
@Slf4j
public class RedisKeyExpiredListener implements MessageListener {private final PatternTopic topic = new PatternTopic("__keyevent@*__:expired");@Autowiredprivate ConsumeService consumeService;@Overridepublic void onMessage(Message message, byte[] pattern) {String topic = new String(pattern);String msg = new String(message.getBody());System.out.println("接收到过期事件:"+msg);}}
创建删除事件监听器类:
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;import lombok.Data;@Component
@Data
public class RedisKeyDeleteListener implements MessageListener {// 监听主题private final PatternTopic topic = new PatternTopic("__keyevent@*__:del");@Overridepublic void onMessage(Message message, byte[] pattern) {String topic = new String(pattern);String msg = new String(message.getBody());System.out.println("收到key的删除,消息主题是:" + topic + ",消息内容是:" + msg);}}
创建一个RedisMessageListenerContainer,并将以上两个事件监听器类,注册到对该容器中。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;@Configuration
public class RedisListenerConfig {@Autowiredprivate RedisKeyDeleteListener redisDeleteListener;@Autowiredprivate RedisKeyExpiredListener redisExpiredListener;@BeanRedisMessageListenerContainer container(RedisConnectionFactory factory){RedisMessageListenerContainer container=new RedisMessageListenerContainer();container.setConnectionFactory(factory);//监听所有key的删除事件container.addMessageListener(redisDeleteListener,redisDeleteListener.getTopic());//监听所有key的过期事件container.addMessageListener(redisExpiredListener,redisExpiredListener.getTopic());return container;}
}
此时,我们可以分别在两个监听器类中,处理对应的事件,来完成自己的业务。