zoukankan      html  css  js  c++  java
  • PHP+Redis秒杀其实很简单

    秒杀这个问题,一直以来都是经典的面试题。但是秒杀也分大小。如果一个产品的用户不超过5w,上来就问双十一级别的秒杀。那就没有意思了~,所以今天就简单聊下一般条件下的秒杀的思路。方法只有两个,一个是装载秒杀商品。一个就是模拟用户进场秒杀。


     
    图片发自简书App

    工具介绍

    首先环境就比较简单

    1. Apache
    2. PHP 7.3
    3. redis

    框架我选择的ThinkPHP5.1 不过这次我主要还是选择贴近原生的写法

    选择apache的原因很简单。自带压力测试工具ab。符合我们的需要。虽然我们知道nginx来做web服务器性能更好。
    php7.* 这个不用多介绍了PHP 7 和 PHP 5的性能不是一个世界的
    redis 虽然可以实现秒杀的方式有很多。redis算是非常常见的缓存和中间件工具了。在性能和上手难度上都是很不错的选择

    一.装载秒杀商品

    我们先假设我们有300个人来抢30件商品。那么我们就在我们的商品库里面装载30件不同id的商品
    秒杀商品一般都是定时添加的。所以我们需要一个定时任务控制器用cli模式执行

    class Crontab
    {
          public function addGoods()
        {
            //设定商品数量
            $count=30;
            $listKey="2019_04_15_goods_list";
            //创建连接redis对象
            $redis = new Redis();
            $redis->connect('127.0.0.1', 6379);
            for ($i=1;$i<=$count;$i++){
                //将商品id push到列表中
                $redis->rPush($listKey,$i);
            }
        }
    }
    

    然后当我们需要装载商品的时候我们使用php命令去执行下我们的方法

    php /项目地址/public/index.php index/crontab/addgoods
    

    用redis客户端查看下商品id是否放入成功


     
    查看商品id

    二.秒杀商品

    秒杀商品其实就是一个将集合中的商品id取出和用户id绑定的过程。只是这个过程进行的非常的快。那么我们将秒杀分为两步,如果秒杀成功,则记录下用户id和商品id 也就是所谓的秒杀订单。如果秒杀失败,我们则简单的记录一个秒杀失败的人数。来确定这次秒杀有多少有效用户参与。

      public function kill()
        {
            //假装是用户的唯一标识
            $uuid=md5(uniqid('user').time());
            //创建连接redis对象
            $redis = new Redis();
            $redis->connect('127.0.0.1', 6379);
            $listKey="2019_04_15_goods_list";
            $orderKey="2019_04_15_buy_order";
            $failUserNum="2019_04_15_fail_user_num";
            if ($goodsId=$redis->lPop($listKey)) {
                //秒杀成功
                //将幸运用户存在集合中
                $redis->hSet($orderKey,$goodsId,$uuid);
            }else{
                //秒杀失败
                //将失败用户计数
                $redis->incr($failUserNum);
            }
            echo "SUCCESS";
        }
    

    压力测试模拟秒杀

    刚刚有提到会使用apache自带的ab做测试
    小试牛刀 300并发 3000访问量

    ab -c 300 -n 3000 http://shop.example.com/index.php/index/index/kill
    

    啥也不说就是干

     
    运行结果

    虽说还是比较慢,但是3000次请求,是全部命中没有死掉的用户。加上我本身docker性能没给到最大。加上只有单机节点。我对这个成绩还是比较满意的

    下面来看看抢到商品的幸运用户

    [root@2f7621a62356 bin]# redis-cli  
    127.0.0.1:6379> HGETALL 2019_04_15_buy_order
    
     
    商品和 用户id的对应关系

    再看看秒杀失败的用户数量


     
    抢购失败次数

    这时候的商品list已经空空如也了。

    好了,今天简单做个秒杀,就介绍到这里。有时候思路比实现的方法更重要。



    链接:https://www.jianshu.com/p/aa18f15e1bf0

  • 相关阅读:
    hdu5289 RMQ+二分
    poj1459 最大流Dinic
    poj2391 最大流+拆点
    poj1087&&hdu1526 最大流
    NOI2004 郁闷的出纳员
    Treap入门(转自NOCOW)
    poj 2892
    vijos 1512
    对拍程序
    poj 3264
  • 原文地址:https://www.cnblogs.com/gaosf/p/13179446.html
Copyright © 2011-2022 走看看