實現思路
方式一
1. 使用redis zset 數據結構 2.使用score排序 score為過期時間點 3.啟動線程不斷取出排序第一個 比較score和當前時間點 如果score小於或等於當前時間 說明此數據過期 需要處理 4.處理完畢在zset中移除
public class TestMain {
private static final String ADDR="39.96.77.182";
private static final int PORT=6379;
//初始化jedis
private static JedisPool jedisPool=new JedisPool(new GenericObjectPoolConfig(),ADDR,PORT,10000);
public static Jedis getJedis() {
return jedisPool.getResource();
}
//消息入隊
public void productionDelayMessage(){
//延遲5秒
Calendar cal1 = Calendar.getInstance();
cal1.add(Calendar.SECOND, 5);
int second3later = (int) (cal1.getTimeInMillis() / 1000);
Long orderId = TestMain.getJedis().zadd("OrderId", second3later, "OID0000001" );
System.out.println(new Date()+"ms:redis生成了一個訂單任務:訂單ID為"+"OID0000001"+"==============="+orderId);
}
//消費者取訂單
public void consumerDelayMessage(){
Jedis jedis = TestMain.getJedis();
while(true){
Set<Tuple> items = jedis.zrangeWithScores("OrderId", 0, 1);
if(items == null || items.isEmpty()){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
continue;
}
int score = (int) ((Tuple)items.toArray()[0]).getScore();
Calendar cal = Calendar.getInstance();
int nowSecond = (int) (cal.getTimeInMillis() / 1000);
if(nowSecond >= score){
String orderId = ((Tuple)items.toArray()[0]).getElement();
Long num = jedis.zrem("OrderId", orderId);
System.out.println(num);
if( num != null && num>0){
System.out.println(new Date() +"ms:redis消費了一個任務:消費的訂單OrderId為"+orderId);
}
}
}
}
public static void main(String[] args) {
TestMain appTest =new TestMain();
appTest.productionDelayMessage();
appTest.consumerDelayMessage();
}
執行結果

方式二: redis過期回調
修改redis 配置 redis.conf 添加notify-keyspace-events Ex

編寫測試demo
新建boot工程 加入redis依賴
新建redisconfig 注入 RedisMessageListenerContainer Bean
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
編寫redis 監聽類 繼承KeyExpirationEventMessageListener
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
System.out.println("監聽到過期的key為:"+expiredKey);
}
}
運行boot工程 使用redis 客戶端 redis desktop manager添加一個key 設置過期時間

延時兩秒 在工程控制太看到輸出

