消息过期通知-reids keyspace notifications

消息过期通知-reids keyspace notifications

了解到使用reids中keyspace notifications功能可以实现消息过期通知

打开redis中keyspace notifications功能

默认情况下,redis中的keyspace notifications功能是关闭的,打开这个功能也非常简单。打开redis.conf文件,找到nofity-keyspace-events一行:

# 关闭就是空字符串 ""
#  notify-keyspace-events ""

# 打开,这里是是过期事件才会通知
notify-keyspace-events Ex

支持的事件:

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.

通知订阅

继承JedisPubSub:

@Component
public class KeySpaceNotifySub extends JedisPubSub {

    private static final Logger LOGGER = LoggerFactory.getLogger(KeySpaceNotifySub.class);

    @Override
    public void onPSubscribe(String pattern, int subscribedChannels) {
        LOGGER.info("onPSubscribe "+pattern + "=" + subscribedChannels);
    }

    @Override
    public void onPMessage(String pattern, String channel, String message) {
        System.out.println(pattern+": "+ channel +": "+ message);
    }

}

随着spring容器启动而订阅(因为redis中的psubscribe操作是阻塞,所以这里重新开启一个线程订阅,不然会一直阻塞web容器,web运行不了):

public class KeySpaceNotifyInitializeBean implements InitializingBean {

    @Autowired
    private JedisPool jedisPool;

    @Autowired
    private KeySpaceNotifySub keySpaceNotifySub;

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("KeySpaceNotifyInitializeBean...");
        Thread thread = new Thread(() -> {
            jedisPool.getResource().psubscribe(keySpaceNotifySub,"__keyevent@0__:expired");
        });
        thread.start();
    }
}

spring-context.xml配置:


<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxIdle" value="${redis.maxIdle}" />
    <property name="maxTotal" value="${redis.maxActive}" />
    <property name="maxWaitMillis" value="${redis.maxWait}" />
    <property name="testOnBorrow" value="${redis.testOnBorrow}" />
bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
    <constructor-arg index="0" ref="jedisPoolConfig"/>
    <constructor-arg index="1" value="${redis.host}" type="java.lang.String"/>
    <constructor-arg index="2" value="${redis.port}" type="int"/>
    
    
bean>
<bean id="keySpaceNotifyInitializeBean" class="com.**.yjy.keynotify.KeySpaceNotifyInitializeBean" />

测试:

127.0.0.1:6379> setEx name 5 hello
OK
127.0.0.1:6379> setEx world 5 world
OK

可以在控制台看到:

KeySpaceNotifyInitializeBean...
[2018-07-22 16:52:27.298] [ INFO] KeySpaceNotifySub onPSubscribe __keyevent@0__:expired=1
...
[2018-07-22 04:52:27,545] Artifact spring-mvc-demo:war exploded: Artifact is deployed successfully
[2018-07-22 04:52:27,545] Artifact spring-mvc-demo:war exploded: Deploy took 5,367 milliseconds
__keyevent@0__:expired: __keyevent@0__:expired: name
__keyevent@0__:expired: __keyevent@0__:expired: world

注意:redis中的expire事件,并不是根据ttl键名为0的时候触发的,而是在真正删除了过期键(key)的时候才触发的。如果删除时间和ttl时间存在时间差,那么通知就不会那么的精确

你可能感兴趣的:(redis问题)