PHP+Redis 商品超賣
阿新 • • 發佈:2020-10-16
第一種使用Redis LIST做佇列(List的Lpop操作是原子性的)
- 思路:先在Redis中根據商品數量生成相應的庫存佇列,當用戶搶購商品時先從佇列中獲取商品,然後再進行下單等相關邏輯處理
- 實踐
生成庫存佇列
<?php public function fillStock(){ $redis = new \Redis(); $redis->connect("redis",6379); $redis->auth("hengda"); $redis->select(1); for($i = 0;$i < 1000;$i++){ $redis->lPush("shop_list",rand(1000000000,99999999999999)); } }
搶購消費佇列
<?php public function purchase(){ $redis = new \Redis(); $redis->connect("redis",6379); $redis->auth("hengda"); $redis->select(1);if(!$redis->lPop("shop_list")){ return response_json(1,["msg"=>"已結束"],"success"); } //TODO 生成訂單佇列 }
第二種使用Redis執行Lua指令碼(執行指令碼的eval操作是原子性的)
- 思路:在redis庫中儲存庫存數,當用戶搶購時先將庫存減1然後再生成訂單對列
- 實踐
<?php public function purchaseLua(){ $redis = new \Redis(); $redis->connect("redis",6379); $redis->auth("hengda"); $redis->select(1); $lua_script = <<<LUA local shop_num_exit = redis.call("get","shop_num"); if shop_num_exit == "0" then return false; else return redis.call("decr","shop_num"); end LUA; $result = $redis->eval($lua_script); if($result === false){ return response_json(1,["msg"=>"已結束"],"success"); } //TODO 生成訂單對列 }