TP使用Redis列表list完成秒杀(限制商品)

23 篇文章 0 订阅
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\cache\driver\Redis;

class Miaosha extends Controller
{

    private $redis = null;
    private $cachekey = null;    //缓存变量名
    private $basket = [];        //私有数组,存放商品信息

    private $store = 50;

    /**
     * 购物车初始化,传入用户id
     */
    public function __construct()
    {
        parent::__construct();

        $this->redis = new \Redis();        // 实例化
        $this->redis->connect('127.0.0.1','6379');
        $this->redis->auth('zxf123456');
    }

    /**
     * 秒杀初始化
     */
    public function Ms_init()
    {
        // 删除缓存列表
        $this->redis->del($this->cachekey);

        $len = $this->redis->llen($this->cachekey);
        $count = $this->store - $len;

        for ($i=0; $i < $count; $i++) { 

            // 向库存列表推进50个,模拟50个商品库存
            $this->redis->lpush($this->cachekey,1);
        }

        echo "库存初始化完成:".$this->redis->llen($this->cachekey);
    }
 

    /**
     * 秒杀入口
     */
    public function index()
    {
        $id = 1;    //商品编号
        
        if (empty($id)) {
            // 记录失败日志
            return $this->writeLog(0,'商品编号不存在');    
        }

        // 计算库存列表长度
        $count = $this->redis->llen($this->cachekey);

        // 先判断库存是否为0,为0秒杀失败,不为0,则进行先移除一个元素,再进行数据库操作
        if ($count == 0) {    //库存为0

            $this->writeLog(0,'库存为0');
            echo "库存为0";
            exit;

        }else{
            // 有库存
            //先移除一个列表元素
            $this->redis->lpop($this->cachekey);

            $ordersn = $this->build_order_no();    //生成订单
            $uid = rand(0,9999);    //随机生成用户id
            $status = 1;
            // 再进行数据库操作
            $data = Db::table('ab_goods')->field('count,amount')->where('id',$id)->find();    //查找商品

            if (!$data) {
                return $this->writeLog(0,'该商品不存在');
            }

            $insert_data = [
                'order_sn' => $ordersn,
                'user_id' => $uid,
                'goods_id' => $id,
                'price'    => $data['amount'],
                'status' => $status,
                'addtime' => date('Y-m-d H:i:s')
            ];

            // 订单入库
            $result = Db::table('ab_order')->insert($insert_data);
            // 自动减少一个库存
            $res = Db::table('ab_goods')->where('id',$id)->setDec('count');

            if ($res) {
                echo "第".$count."件秒杀成功";
                $this->writeLog(1,'秒杀成功');
            }else{
                echo "第".$count."件秒杀失败";
                $this->writeLog(0,'秒杀失败');
            }
        }
    }

    /**
     * 生成订单号 这里也可以使用雪花算法
     */
    public function build_order_no()
    {
        return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
    }

    /**
     * 生成日志  1成功 0失败
     */
    public function writeLog($status = 1,$msg)
    {
        $data['count'] = 1;
        $data['status'] = $status;
        $data['addtime'] = date('Y-m-d H:i:s');
        $data['msg'] = $msg;
        return Db::table('ab_log')->insertGetId($data);
    }

}

通过list 弹出商品能达到拒绝超卖 , 但是会有秒杀到不付款的情况 , 根据业务需求可以再制作倒计时功能,倒计时结束后通过lpush放回列表中

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苗先生的PHP记录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值