用redis实现限时抢购,并且防止超卖和重复购买

废话不多BB,直接上代码:

1、引入类库文件:ShopList.php


<?php

class ShopList{

    function __construct()
    {
    }

    /**
     * 添加队列
     * @param $redis    redis链接对象
     * @param $uid      用户ID
     * @param $num      活动出售商品总量
     */
    function shopList($redis,$uid,$num)
    {
        //判断当前用户是否有对应的订单,有就退出并给出友好提示
        if ($redis->sismember('tvUser',$uid)) {
            echo 2;exit;
        }

        while (true) {
            //检查商品是否已经超卖,没有添加队列,大于活动出售商品总量退出并给出友好提示
            if ($redis->llen('shop') < $num)
            {
                //加入队列
                $redis->lpush('shop',$uid);
                //加入已购买用户集合
                $redis->sAdd('tvUser',$uid);
                $flag = 1;
            }else{
                $flag = 3;
            }
            echo $flag;
            break;
        }
    }

    /**
     * 异步执行操作
     * @param $redis    redis链接对象
     * @param $length   活动出售商品总量
     */
    function carryList($redis,$length)
    {
        //获取队列长度
        $len = $redis->llen('shop');
        //长度为0时停止执行
        if(empty($len))
        {
            exit;
        }
        //执行次数
        $num = 0;

        while (true) {
            sleep(1);   //延迟执行
            $uid = $redis->rpop('shop');    //移除队列中最后一个元素
            if ($uid > 0) {
                //create order 生成用户对应的订单
                $redis->sadd('okUser',$uid); //总计处理的用户数
                $redis->srem('tvUser',$uid); //移除购买成功用户信息
                $num++;

            } else {
                //insert log
                $redis->sadd('errorOrder',$uid); //添加处理失败的用户信息

            }
            //当执行大于等于活动出售商品总量时退出循环
            if ($num >= $length) {
                break;
            }
        }
    }

}

?>

2.添加 队列:lpush.php

<?php
//引入类文件
include 'ShopList.php';

//链接redis服务器
$redis = new Redis();
$link = $redis->connect('redis服务器IP地址', 6379);
$redis->auth('redis密码'); //没有密码可以省略

$uid = $_GET['uid'];         //用户id
$num = 5;                    //活动出售商品总量
$redisObj = new ShopList();  //实例化类文件

$redisObj -> shopList($redis,$uid,$num); //调取添加方法执行添加操作

3.异步操作队列:rpop.php

<?php
//引入类文件 
include 'ShopList.php';

//链接redis服务器
$redis = new Redis();
$link = $redis->connect('redis服务器IP地址', 6379);
$redis->auth('redis密码'); //没有密码可以省略

$num = 5; //活动出售商品总量
$redisObj = new ShopList(); //实例化类文件

$redisObj -> carryList($redis,$length);  //调取方法执行生成订单操作

?>

4.设置计划任务异步处理添加订单操作:

分 时 日 月 周           php安装目录           脚本文件位置

 *   *    *   *    * /usr/local/php/bin/php  /var/www/html/shell/rpop.php

猜你喜欢

转载自blog.csdn.net/PHPArchitect/article/details/81355891