Redis列队处理抢购,秒杀
库存列队格式 , 四条数据表示商品库存数量为4
```
array(4) {
[0] => string(1) "1"
[1] => string(1) "1"
[2] => string(1) "1"
[3] => string(1) "1"
}
```
原理, 用户访问该产品的时候设置队列库存 ,当用户点击支付的时候,生成订单,移除一个库存 , 当订单取消的时候增加一个库存
```
~~~
<?php
namespace app\home\controller;
use think\Db;
/**
* Class Redis
* @package app\home\controller
*/
class Redis extends Common
{
public $goods_id;
public $user_queue_key;
public $goods_number_key;
public $user_id;
public $times;
public function __construct()
{
parent::__construct();
$goods_id = input("goods_id", '0', 'intval');
if (!$goods_id) {
$this->error('商品不存在');
}
$this->user_id=11;
if (!$this->user_id) {
$this->error('请先登录');
}
$this->times = time();
$this->goods_id = $goods_id;
$this->user_queue_key = "goods_" . $goods_id . "_user";//当前商品队列的用户情况
$this->goods_number_key = "goods" . $goods_id;//当前商品的库存队列
}
/*
* redis连接
*/
private function connectRedis()
{
$redis = new \Redis();
$redis->connect('127.0.0.1', '6379');
return $redis;
}
/*
* 查看商品,生成商品库存列队
*/
protected function judgment_goods()
{
$where = [
['id', '=', $this->goods_id],
['start_time', '<', $this->times],//秒杀开始时间
['end_time', '>', $this->times],//秒杀结束时间
];
$goods = Db("goods111")->where($where)->find();
if (!$goods) {
$this->error("当前秒杀已结束!");
}
if ($goods['number'] <= 0) {
$this->error("当前产品已经秒杀完!");
}
return $goods;
}
/**
* 访问产品前先将当前产品库存队列
* @access public
* @author bieanju
*/
public function before_detail()
{
$goods = $this->judgment_goods();
$redis = $this->connectRedis();
$getUserRedis = $redis->lLen($this->user_queue_key); // 获取列队会员的数量
$gnRedis = $redis->lLen($this->goods_number_key); //获取商品库存数量
/* 如果没有会员进来队列库存 */
if (!$getUserRedis && !$gnRedis) {
for ($i = 0; $i < $goods['number']; $i++) {
$redis->lPush($this->goods_number_key, 1); //新增商品库存数量
}
}
$resetRedis = $redis->lLen($this->goods_number_key); //获取商品库存数量
if (!$resetRedis) {
$this->error("系统繁忙,请稍后抢购!");
}
return view();
}
/**
* 用户点击抢购后的操作
* @access public
* @author bieanju
*/
public function goods_number_queue()
{
$this->judgment_goods();
/* redis 队列 */
$redis = $this->connectRedis();
/* 进入队列 */
$goods_number_key = $redis->lLen($this->goods_number_key); //获取商品库存数量
if (!$goods_number_key) {
die('商品库存不足');
}
$redis->lPush($this->user_queue_key, $this->user_id);
$user_id = $redis->lPop($this->user_queue_key); //移除并且获取列队中用户ID
//创建订单,并且减少库存
$data = [
'user_id' => $user_id,
'goods_id' => $this->goods_id,
'number' => 1,
'create_time' => time(),
'type' => 1,//未支付
];
$result = Db::name('orders')->insert($data);
if (!$result) {
die('操作失败');
}
$redis->lPop($this->goods_number_key);//减少库存
$this->success('抢购成功');
}
/**
* 可用定时器, 定时执行该方法, 判断订单是否过期
* 抢购中,超时未支付订单处理办法
*/
public function order_no_pay()
{
//更改订单状态为已取消
$this->judgment_goods();
/* redis 队列 */
$redis = $this->connectRedis();
//恢复库存
$redis->lPush($this->goods_number_key, 1);
}
/*
* 注意 , 下单后指定时间取消订单会出现一个问题,
* 如15分钟未支付则将订单改为已取消, 用户在 14分59秒时候发起支付, 支付成功后, 该订单会取消(此时需要做退款处理,或者人工更改订单状态处理)
*/
}
~~~
```
- ThinkPHP
- MySql
- 事务
- 漏洞修复
- jQuery
- select搜索下拉框,多选,全选等
- 移动端富文本编辑器
- 复制内容
- ajax请求
- PHP
- 基本语法
- 关于屏蔽“未定义数组下标:0”错误的问题
- PHP文件操作
- 使用PhpOffice 在PHP7.3中导出数据报错问题
- curl
- PHP生成PPT
- Redis
- 如何在PHP中安装Redis扩展
- Redis队列,秒杀,抢购
- 压力测试(ab)
- apache ab压力测试
- 微信
- 微信支付
- 微信分享
- 授权登录
- 微信公众号服务器
- 自动回复
- 微信发起支付html页面
- composer
- 安装
- 二维码的生成
- Excel导入导出
- 数据采集
- 采集列表
- 采集内容详情
- 图片采集
- Linux
- 常用命令
- 解压压缩
- 服务器
- 服务器运行缓慢的原因
- IIS 隐藏index.php
- 端口检测
- Nginx
- 数据库
- Oracle数据库
- MySql
- 新增MySql
- Field字段
- Tp验证码加载不出来,解决办法
- API接口
- Google API
- 织梦CMS支付接口
- SMTP发送邮箱问题
- Could not connect to SMTP host
- 阿里云API接口
- 支付宝新版配置
- 腾讯API接口
- 安装方法
- 百度地图API
- 通过ip地址获取当前城市
- 常用笔记
- yarn