使用 Redis 實現延時隊列
場景描述:訂單在下單之後一定時間內沒有支付,則關閉該訂單
實現方式:用戶下單-> 生成訂單記錄-> 將訂單信息推入延時隊列任務中-> 到時間檢查訂單的支付狀態(未支付則關閉訂單)
使用redis 實現延時隊列 的功能
思路: 用戶在調用延時任務的方法時,需要傳入兩個參數(任務腳本,延時時間)。
通過redis 有序集合來存儲執行時間,每次取出第一個元素,執行時間與當前時間對比,如果小於等於當前時間則執行改腳本。並且移除改元素。
由於redis 集合具有唯一性,所以不能放在一個表裏。
- string 類型的message_id 用來實現生成唯一id ,作爲2和3連接的樞紐
- 有序集合類型 message_delay 存儲執行時間
- hash 類型存儲任務
首先,創建一個queue 文件:
//連接Redis
$redis = new Redis();
$redis->connect('107.0.0.1', 6379);//這裏沒有設置登錄賬號
//這裏只是用來測試,job 應是一個實例
$job = 4;
$delay = 10*60; //延時時間單位改爲分鐘。
queue($job,$delay,$redis);
//入隊列
function queue($job,$delay,$redis){
$num = $redis->INCR("message_id");
$redis->ZADD("message_delay", time()+$delay, $num);
$redis->HSET("messages",$num,$job);
創建job 文件
//連接Redis
$redis = new Redis();
$redis->connect('107.0.0.1', 6379);//這裏沒有設置登錄賬號
function queuePush($redis){
$uids_d = $redis->ZRANGE("message_delay", 0, 0, TRUE);//取出一個元素
foreach($uids_d as $key => $val){
if($val <= time()){
//移除delay 和 message 數據
$redis->zrem("message_delay",$key);
$redis->HDEL("messages",$key);
return queuePush($redis); //遞歸調用
}else{
return false;
}
}
}
最後將你的 job.php
文件放到定時任務中就可以了。
這裏只是一個實現思路,實際中應該使用面向對象的方法去實現。並且進行優化。