基於Redis的消息隊列實現固定庫存商品搶購
//商品總庫存須要在後臺寫入到庫存隊裏中,提早寫入
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$redis->auth('alloc');
$redis->select(1);
//獲取庫存並減一寫入隊列
$k = $redis->lPop('sale_count');
echo $k;
if($k>1){
if($k-1 == 0){
$redis->del('sale_count');
}else{
$redis->lPush('sale_count',$k-1);
}
echo '搶購成功!';
}else{
echo '售賣完畢!';
}
基於上面的基礎解決購買數量存儲,超時不支付訂單取消訂單並恢復庫存
<?php
//商品總庫存須要在後臺寫入到庫存隊裏中,提早寫入
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('alloc');
$redis->select(1);
//
$user_id = rand(1, 10000);//隨機模擬用戶ID 不去重複了實際狀況下沒有重複的
$buy_num = rand(1, 9);//隨機模擬購買數量
//獲取庫存並減一寫入隊列
$k = $redis->lPop('sale_count');
if ($k > 1) {
if ($k - $buy_num <= 0) {
exit('庫存不足');
}else{
$redis->rPush('get_good_list', $user_id);//將搶到順序插入隊列,在守護進程1中處理
$redis->setex($user_id, 1800, $buy_num);//設置超時時間30分鐘
$redis->rPush('sale_count', $k - $buy_num);
}
echo '搶購成功!,請五分鐘內支付';
} else {
echo '售賣完畢!';
}
<?php
##Daemon1.php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('alloc');
$redis->select(1);
//while (1){
$user_id = $redis->lPop('get_good_list');
if($user_id){
//獲取購買數量
$buy_num = $redis->get($user_id);
//建立訂單
$order_no = createOder($user_id,$buy_num);
//設置訂單超時時間
$redis->setex($order_no,300,1);//5分鐘未支付通知Daemon2.php
}
//}
<?php
#Daemon2.php
ini_set('default_socket_timeout', -1); //不超時
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('alloc');
$redis->select(1);
//不超時
$redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
//建立事件監聽,__keyevent@1__:expired,數字1表明數據庫序號
$redis->psubscribe(array('__keyevent@1__:expired'), 'keyCallback');
// 回調函數,這裏寫處理邏輯
function keyCallback($redis, $pattern, $chan, $order_no){
//獲取訂單信息 獲取購買數量
$buy_num = getOderInfo($order_no);
//關閉訂單
closeOrder();
//加入庫存
$redis->rPush('sale_count',$redis->lPop('sale_count')+$buy_num);
}