公司业务,为了对抗高并发业务,使用redis队列机制,大家可以一起参考参考
1. 用户点击某个商品,首先进入的是商品详情页面,这时候我们将商品库存进行入队列
private $user_queue_key; private $goods_number_key; private $user_id; private $goods_id; public function __construct(){ $this->x_pi = 3.14159265358979324 * 3000.0 / 180.0; parent::__construct(); $goods_id = intval($_GET['goods_id']); $area_id = intval($_GET['area_id']); if($goods_id){ $this->goods_id = $goods_id; $this->user_queue_key = "goods_".$goods_id."_user";//当前商品队列的用户情况 $this->goods_number_key = "goods".$goods_id;//当前商品的库存队列 } $this->user_id = $this->user_id ? $this->user_id : $_SESSION['wap_member_info']['userid']; }
初始化抢购商品的库存队列
/*******************判断商品库存够不够,进行队列*************************/ /*******************当天库存数量是否大于当天下单量订单数量******/ $member_id = $this->user_id; $m = Model('order'); $redis = new Redis(); $redis->connect(C('redis.master.host'), C("redis.master.port")); $goods_orders = $m->getOrderAndOrderGoodsLists($goods_detail['goods_info']['goods_id']); $order_count = count($goods_orders); if($goods_detail['goods_info']['goods_storage'] > $order_count){ /*队列*/ $getUserRedis = $redis->hGetAll("{$this->user_queue_key}"); $gnRedis = $redis->llen("{$this->goods_number_key}"); /* 如果没有会员进来队列库存 */ if(!count($getUserRedis) && !$gnRedis){ for ($i = 0; $i < $goods_detail['goods_info']['goods_storage']; $i ++) { $redis->lpush("{$this->goods_number_key}", 1); } } $resetRedis = $redis->llen("{$this->goods_number_key}"); if(!$resetRedis){ return callback(false, '系统繁忙,请稍后抢购!'); } }else{ return callback(false, '当前商品已经卖完!'); } /*******************判断商品库存够不够,进行队列*************************/ /*******************当天库存数量是否大于当天下单量订单数量******/
2. 当用户点击立即购买按钮的时候,将该商品用户进行队列
/*******************抢购商品前处理当前会员是否进入队列*************************/ $res = $this->goods_number_queue($result, $member_id); if($res == 1){ return callback(false, '亲,您已进入购买排队,请重试!'); }else{ /*******************抢购商品前处理当前会员是否进入队列*************************/ if(!$result['state']){ return $result; } //得到页面所需要数据:收货地址、发票、代金券、预存款、商品列表等信息 $result = $this->getBuyStep1Data($member_id, $result['data']); return $result; }
抢购时的逻辑处理:
/** * 抢购商品前处理当前会员是否进入队列 * @access public * @author bieanju */ public function goods_number_queue($result, $member_id){ $redis = new Redis(); $redis->connect(C('redis.master.host'), C("redis.master.port")); foreach($result['data']['goods_list'] as $k => $v){ /*进入队列*/ $goods_number_key = "goods" . $v['goods_id'];//当前商品的库存队列 $user_queue_key = "goods_" . $v['goods_id'] . "_user";//当前商品队列的用户情况 $goods_number_keys = $redis->llen("{$goods_number_key}"); if(!$redis->hGet("{$user_queue_key}", $member_id)){ $goods_number_keys = $redis->lpop("{$goods_number_key}"); } if($goods_number_keys){ // 判断用户是否已在队列 if(!$redis->hGet("{$user_queue_key}", $member_id)){ // 插入抢购用户信息 $userinfo = array( "user_id" => $member_id, "create_time" => time() ); $redis->hSet("{$user_queue_key}", $member_id, serialize($userinfo)); return 1; }else{ //获取购物车栏 return 2; } }else{ output_error('系统繁忙,请重试!'); } } }