zoukankan      html  css  js  c++  java
  • 利用redis List队列简单实现秒杀 PHP代码实现

    利用redis List队列简单实现秒杀 PHP代码实现

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/m_nanle_xiaobudiu/article/details/80479666

    一 生产者producer部分

    --------------------------------producer 部分注释------------------------------------------------------------

    用户在页面请求之后, 获取到用户uid , 跳转到这个加入队列的方法 (这里直接在producer中模拟了多个uid)

    在方法内部判断redis队列长度是否已经达到要求, 如果没有超出, 则执行加入队列的操作 (这里为了简洁,没有封装成方法)

    注: producer.php没有进行数据库的操作,只有接受uid和其他值的操作, 数据库操作一律放在消费者consumer.php中

    --------------------------------producer 注释结束-----------------------------------------------------------------------

    生产者代码 producer.php:

    1.  
      <?php
    2.  
       
    3.  
      //连接redis数据库
    4.  
      $redis = new Redis();
    5.  
      $redis->connect('127.0.0.1',6379);
    6.  
      $redis_name = 'secKill3';
    7.  
       
    8.  
      //模拟100人请求秒杀(高压力)
    9.  
      for ($i = 0; $i < 100; $i++) {
    10.  
      $uid = rand(10000000, 99999999);
    11.  
      //获取当前队列已经拥有的数量,如果人数少于十,则加入这个队列
    12.  
      $num = 10;
    13.  
      if ($redis->lLen($redis_name) < $num) {
    14.  
      $redis->rPush($redis_name, $uid);
    15.  
      echo $uid . "秒杀成功"."<br>";
    16.  
      } else {
    17.  
      //如果当前队列人数已经达到10人,则返回秒杀已完成
    18.  
      echo "秒杀已结束<br>";
    19.  
      }
    20.  
      }
    21.  
      //关闭redis连接
    22.  
      $redis->close();
    23.  
       

    注: 执行完producer.php文件,本地redis数据库第0号数据库中应该有一个键名为"secKill3"的List队列,像这样

    二 消费者consumer部分

    ------------------------------消费者部分注释---------------------------------------------

    消费者一直读取redis数据库中指定队列,一有值,立即取出,并进行相应数据库操作

    ------------------------------消费者部分注释结束----------------------------------------

    消费者代码 consumer.php

    1.  
      <?php
    2.  
       
    3.  
      //设置redis数据库连接及键名
    4.  
      $redis = new Redis();
    5.  
      $redis->connect('127.0.0.1');
    6.  
      $key = 'secKill3';//redis数据库key [注:默认redis数据库选择第0号数据库]
    7.  
       
    8.  
      //PDO连接mysql数据库
    9.  
      $dsn = "mysql:dbname=test;host=127.0.0.1";
    10.  
      $pdo = new PDO($dsn, 'root', '123456');
    11.  
       
    12.  
      //死循环
    13.  
      //从队列最前头取出一个值,判断这个值是否存在,取出时间和uid,保存到数据库
    14.  
      //数据库插入失败时,要有回滚机制
    15.  
      //注: rpush 和lpop是一对
    16.  
       
    17.  
      while(1) {
    18.  
      //从队列最前头取出一个值
    19.  
      $uid = $redis->lPop($key);
    20.  
      //判断值是否存在
    21.  
      if(!$uid || $uid == 'nil'){
    22.  
      sleep(2);
    23.  
      continue;
    24.  
      }
    25.  
      //生成订单号
    26.  
      $orderNum = build_order_no($uid);
    27.  
      //生成订单时间
    28.  
      $timeStamp = time();
    29.  
      //构造插入数组
    30.  
      $user_data = array('uid'=>$uid,'time_stamp'=>$timeStamp,'order_num'=>$orderNum);
    31.  
      //将数据保存到数据库
    32.  
      $sql = "insert into student (uid,time_stamp,order_num) values (:uid,:time_stamp,:order_num)";
    33.  
      $stmt = $pdo->prepare($sql);
    34.  
      $res = $stmt->execute($user_data);
    35.  
      //数据库插入数据失败,回滚
    36.  
      if(!$res){
    37.  
      $redis->rPush($key,$uid);
    38.  
      }
    39.  
      }
    40.  
       
    41.  
      //生成唯一订单号
    42.  
      function build_order_no($uid){
    43.  
      return substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8).$uid;
    44.  
      }

    注: 执行完consumer.php之后,数据库对应数据表应该有数值

    到此,秒杀结束

    备注:

    用到的student数据表结构sql

    1.  
      CREATE TABLE `student` (
    2.  
      `uid` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'uid',
    3.  
      `username` varchar(20) NOT NULL DEFAULT '',
    4.  
      `time_stamp` int(11) NOT NULL DEFAULT 0,
    5.  
      `order_num` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
    6.  
      PRIMARY KEY (`uid`) USING BTREE,
    7.  
      key (time_stamp)
    8.  
      ) ENGINE = MyISAM default charset=utf8;
     
  • 相关阅读:
    git 创建项目
    【转载】Nginx-Lua模块的执行顺序
    【转】微信oauth授权过程
    vps
    【转载】centos安装字体
    【转载】TortoiseGit图标消失
    【转载】linux权限
    js 获取url 中的参数;
    手机下拉/上拉刷新(基于jq或者zepto)
    vscode快捷键
  • 原文地址:https://www.cnblogs.com/guiyishanren/p/11563862.html
Copyright © 2011-2022 走看看