前言
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后控制台輸出如下:
- 接下來就可以去處理相應的業務了。
