laravel简单秒杀实现

业务:平台推出商品秒杀活动,活动中可以添加多个商品,即同时有多个商品参与了秒杀,但每个人对同一个商品只能成功抢购一个,预计有1w人参加,即最高并发数10000。

思路:最常见的方法是使用reids来实现,创建两个队列,商品库存队列和抢购成功用户队列,用户抢购时,先判断用户是否在抢购成功用户队列中,是直接返回已抢购成功,否则从商品库存队列取出一个商品库存,取得成功将用户加入抢购成功用户队列,取出失败则直接返回已抢购完。在活动结束或数据库闲时处理抢购成功用户队列,生成待支付订单,提醒用户支付。

实现步骤:

  1. 秒杀活动生成后创建商品库存队列,队列使用的是list结构。
    $num = 100;  //商品库存
    $goodsid = 1; //商品id
    //生成对应商品库存队列
    $goods = "goods:".$goodsid;
    for ($i=0; $i < $num; $i++) { 
        Redis::lpush($goods, 1);
    }

     

  2. 开始秒杀:

    $goodsid = $request->input("goodsid"); //商品id
    $userId = $request->input("userId"); //抢购用户id
    
    $goods = "goods:".$goodsid;                //对应商品库存队列
    $robSuccessUser = "successUser".$goodsid; //对应商品抢购成功用户队列
    
    $result = Redis::sismember($robSuccessUser,$userId);
    if ($result) {
        return "已经抢购过了";
    }
    
    $count = Redis::lpop($goods);
    if (!$count) {
        return '已经抢光了哦';
    }
    $success = Redis::sadd($robSuccessUser, $userId);
    if(!$success){
        //已经在成功队列里了,加回库存,防止的是同个用户并发请求
        Redis::lpush($goods, 1);
        return "已经抢购过了";
    }
    
    //以下根据需要可以使用redis延迟队列生成订单,或者在数据库闲时再生成订单
    .......
    

    抢购成功用户队列使用的是set结构,添加进userId时如果set里已经存在则返回0,成功返回1,使用这个特性可以进行最后判断用户是否已经在成功队列中了,防止同个用户并发多个请求且通过了$result的判断(该步骤也可以使用多一个队列来做限制,用户请求队列,用户请求来到时先加入请求队列,只允许接受一次请求,之后的请求直接拒绝)。

         总的来说是使用了redis的原子性,即使有多个用户同时到达,也是依次取出一个库存,这样就能保证商品不会被超卖。

         关于减库存问题,推荐生成待支付订单立减库存,然后再将订单加入检查过期的延迟队列,规定时间后还没支付将订单过期然后加回库存。

优化

  • 将秒杀系统单独部署,跟现有项目隔离开,避免造成整个项目崩溃。
  • 将秒杀商品详情页面重新设计,将页面内容静态化,用户请求页面不经过应用服务。
  • 为了避免用户直接访问下单页面URL,需要将改URL动态化,即使秒杀系统的开发者也无法在秒杀开始前访问下单页面的URL。办法是在下单页面URL加入由服务器端生成的随机数作为参数,在秒杀开始的时候才能得到。
  • 将秒杀按钮置灰,到时间变亮,限制用户x秒点击一次。
  • 过载保护,如果检测到系统满负载,直接拒绝请求。
  • 检测IP请求频率,过高的时候弹出验证码或拒绝请求。
  • 使用负载均衡。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值