java 监听redis过期key事件实现延迟队列功能

2020-09-14 06:30|来源: 领悟书生

java 监听redis过期key事件,可以实现简单的延迟队列功能。


实现起来也特别简单,方法如下:

一、开启Redis的key过期事件监听,修改后重启

vim /opt/redis/redis.conf

#
# PUBLISH __keyspace@0__:foo del
# PUBLISH __keyevent@0__:del foo
#
# It is possible to select the events that Redis will notify among a set
# of classes. Every class is identified by a single character:
#
#  K     Keyspace events, published with __keyspace@<db>__ prefix.
#  E     Keyevent events, published with __keyevent@<db>__ 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.
#
#  The "notify-keyspace-events" takes as argument a string that is composed
#  of zero or multiple characters. The empty string means that notifications
#  are disabled.
#
#  Example: to enable list and generic events, from the point of view of the
#           event name, use:
#
#  notify-keyspace-events Elg
#
#  Example 2: to get the stream of the expired keys subscribing to channel
#             name __keyevent@0__:expired use:
#
notify-keyspace-events Ex
#
#  By default all notifications are disabled because most users don't need
#  this feature and the feature has some overhead. Note that if you don't
#  specify at least one of K or E, no events will be delivered.
#notify-keyspace-events ""


二、初始化RedisMessageListenerContainer bean

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 {
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }
}


三、实现KeyExpirationEventMessageListener,监听key过期事件,完成业务逻辑处理

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

/**
 * 监听 redis 过期 key
 * __keyevent@*__:expired
 */
@Slf4j
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String expiredKey = message.toString();

        log.info("redis 过期,key:{}",expiredKey);

        //......
    }
}


相关问答

更多
  • 很难实现吧? 即使是满屏窗口的话,下面的任务栏也不可能监听... 要做的话应该还是用鼠标事件监听..
  • 不是通过线程实现的,它是通过一种注册--通知机制实现的。 在java的设计模式中,有一种模式叫:观察者模式,和这个类似。
  • java 事件监听[2022-03-08]

    import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import java.util.*; public class Demo1 extends JFrame implements ActionListener { int i=0; ArrayList al = new ArrayList(2); JPanel img=new JPa ...
  • lz你要明白观察者模式就可以了 这个是我写的 事件、事件源和观察者 明白这个你就明白事件监听了 事件 package test; public class Event { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Event(String name) { super(); this.name = name ...
  • import javax.swing.*; import java.awt.*; import java.awt.event.*; class test extends JFrame implements Runnable{ public static int x,y,direction=0; public test(){ this.setSize(600,400); this.setVisible(true); x=this.getContentPane().getWidth()/2; y=this.ge ...