前言
SpringBoot + Redis 可以用 Redis 的键空间通知机制实现类似延迟消息队列的功能 ,Redis2.8 后可以通过键空间通知接收那些以某种方式改变了Redis数据空间的事件通知,关于 Redis 键空间通知的配置 Redis-x64-3.2 键空间通知(keyspace notification) 之前有介绍,这里只是介绍 SpringBoot 中的同理实现。
环境
SpringBoot2.5.3 + Redis-x64-3.2.1
具体实现
- 启动 redis,配置文件 redis.windows.conf 中设置键空间通知事件为Ex
notify-keyspace-events Ex
- application.yml
redis:
localhost: localhost
port: 6379
database: 7
password:
# 过期事件订阅,接收7号数据库中所有key的过期事件
listen-pattern: __keyevent@7__:expired
- Redis 事件广播配置类
import com.coisini.springbootlearn.core.listener.RedisMessageListener;
import org.springframework.beans.factory.annotation.Value;
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.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
@Configuration
public class RedisListenerConfiguration {
@Value("${spring.redis.listen-pattern}")
public String pattern;
@Bean
public RedisMessageListenerContainer listenerContainer(RedisConnectionFactory redisConnection) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnection);
/**
* Topic是消息发布(Pub)者和订阅(Sub)者之间的传输中介
*/
Topic topic = new PatternTopic(this.pattern);
container.addMessageListener(new RedisMessageListener(), topic);
return container;
}
}
- Redis 事件广播监听器
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
public class RedisMessageListener implements MessageListener {
/**
* Redis 事件监听回调
* @param message
* @param pattern
*/
@Override
public void onMessage(Message message, byte[] pattern) {
byte[] body = message.getBody();
String expiredKey = new String(body);
System.out.println("监听到已过期的key:" + expiredKey);
/**
* 监听到过期事件回调
* TODO:
*/
}
}
- 测试接口
@RestController
@RequestMapping("/redis")
public class RedisController {
@Autowired
private StringRedisTemplate redisTemplate;
@GetMapping(value = "/setExpiredVal")
public String setExpiredVal(@RequestParam String name) {
// 设置 20s 后过期
redisTemplate.opsForValue().set("name", name, 20, TimeUnit.SECONDS);
return "setVal is ok";
}
}
- 访问接口
- 20s后控制台输出如下:
- 接下来就可以去处理相应的业务了。