问题概述
最近根据运营那边提供BUG反馈信息提示,出现了仓库商品冻结数量少了,导致出库异常现象。仓库商品库存信息 表设计是库存num,冻结数frozen_num。当下订单的时候,frozen_num + 1。订单结束,商品库存num - 出库数量,冻结数frozen_num - 出库数量。但是在高并发下,多个请求同时进来,订单下了多个,frozen_num只加了1,那样出库的时候就会产生异常。
初步方案选择,利用redis的原子性,实现锁
1、Redis SETNX
Redis SETNX的用法是SETNX key value。而返回值,如果设置key成功会返回1,没有被设置会返回0。 简单说就是SET if Not eXists,不存在就可以被设置。
然后根据这个特性,用SETNX的value设置过期时间,结合Redis DEL key [key …],用过期时间和程序 是否执行完成,去判断是否可以删除这个key来实现原子性控制。伪代码如下:
if 获取锁成功
1、执行程序
2、解锁
else
//获取锁失败,判断过期时间
if 过期并且超时,
1、解锁
if 再次获取锁
1.执行程序
2、解锁
else
不处理,请求结束
}
获取锁失败,判断value这个过期时间解锁很好的解决了进程异常解锁程序不执行产生死锁问题,但是程序解锁再获取锁的过程 是非原子性的,所以会存在极端现象,假设有进程P1、P2,会出现如下情况。
- 1、P1和P2都获取锁失败,同时进行过期判断,并且都通过。
- 2、P1解锁成功,再获取锁。
- 3、P2又解锁成功,也获取了锁。
- 4、P1、P2同时获取锁成功。
不过官方给了替换方案,原话为
Anyway even assuming a single-instance locking primitive, starting with 2.6.12
it is possible to create a much simpler locking primitive, equivalent to the
one discussed here, using the SET command to acquire the lock, and a simple
Lua script to release the lock. The pattern is documented in the SET command
page.
表达的就是从redis 2.6.12版本起,可以用set实现setnx功能并且可以设置锁过期时间和原子性语言的lua脚本释放锁,去替换了setnx。
2、Redis SET
用了set之后程序就不用去判断是否过期去程序解锁了,也实现了原子性。伪代码变为:
if 获取锁成功
1、执行程序
2、解锁
else
//获取锁失败
1、不处理
}
演示代码
数据库
订单表
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`num` int(11) NOT NULL DEFAULT '0' COMMENT '销售商品数量',
`store_depot_batch_id` int(11) NOT NULL COMMENT '门店仓库批次id',
`create_time` timestamp NULL DEFAULT NULL COMMENT '添加时间,',
`update_time` timestamp NULL DEFAULT NULL COMMENT '更新时间',
`delete_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='订单表';
门店仓库批次表
DROP TABLE IF EXISTS `depot_store_depot_batch`;
CREATE TABLE `depot_store_depot_batch` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`num` int(11) NOT NULL DEFAULT '0' COMMENT '总数量,有效数量=总数-冻结数量',
`frozen_num` int(11) NOT NULL DEFAULT '0' COMMENT '冻结数量',
`create_time` timestamp NULL DEFAULT NULL COMMENT '添加时间,入库时间',
`update_time` timestamp NULL DEFAULT NULL COMMENT '更新时间',
`delete_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='门店仓库批次管理';
INSERT INTO `depot_store_depot_batch` VALUES(1,10,0,NOW(),NOW(),NULL);
门店仓库批次冻结操作表
DROP TABLE IF EXISTS `depot_store_depot_batch_frozen_record`;
CREATE TABLE `depot_store_depot_batch_frozen_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`depot_store_depot_batch_id` int(11) NOT NULL COMMENT '门店仓库批次管理id',
`before_frozen_num` int(11) NOT NULL COMMENT '仓库冻结数量变动前',
`after_frozen_num` int(11) NOT NULL COMMENT '仓库冻结数量变动后',
`frozen_num` int(11) DEFAULT '0',
`desc` varchar(100) NOT NULL COMMENT '描述',
`create_time` timestamp NULL DEFAULT NULL COMMENT '添加时间',
`update_time` timestamp NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='门店仓库冻结记录';
代码,实现下单、更新仓库冻结数和添加冻结操作记录
没有加redis锁的代码
<?php
/**
* Created by PhpStorm.
* User: chunpat
* Date: 2019/11/2
* Time: 11:32 AM
*/
$pdo = new PDO('mysql:host=127.0.0.1;dbname=store', 'root', '123456789');
//销售数量
$num = $_GET['num'] ?? 1;
try{
//查询门店仓库批次信息
$depotStoreDepotBatchSql="select * from `depot_store_depot_batch` where id =1 limit 1";
$depotStoreDepotBatchRes = $pdo->query($depotStoreDepotBatchSql)->fetch();
//操作后冻结数量
$afterFrozenNum = $num + $depotStoreDepotBatchRes['frozen_num'];
$activeNumber = $depotStoreDepotBatchRes['num'] - $afterFrozenNum;
//开启事务
$pdo->beginTransaction();
if($activeNumber < 0){
throw new Exception('商品已售罄了');
}
//下单主表
$orderSql ="insert into `order` VALUES (null,{$num},1,NOW(),NOW(),null)";
$pdo->query($orderSql);
$orderId = $pdo->lastInsertId();
if($orderId)
{
$depotStoreDepotBatchUpdateSql="update `depot_store_depot_batch` set `frozen_num`={$afterFrozenNum} WHERE id=1";
$pdo->query($depotStoreDepotBatchUpdateSql);
//冻结记录操作sql
$actionSql ="insert into `depot_store_depot_batch_frozen_record` VALUES (null,1,{$depotStoreDepotBatchRes['frozen_num']},{$afterFrozenNum},{$num},'并发测试',NOW(),NOW())";
$pdo->query($actionSql);
//提交事务
$pdo->commit();
}
echo '下单成功,订单id为' . $orderId;
}catch (\Exception $e){
//回滚事务
$pdo->rollBack();
echo $e->getMessage();
}
ab压力测试,ab -n 100 -c 10 http://127.0.0.1:83/redis.php,然后查看三个表mysql记录。
查看Order表情况,显示了35row order。
mysql> select * from `order`;
+----+-----+----------------------+---------------------+---------------------+-------------+
| id | num | store_depot_batch_id | create_time | update_time | delete_time |
+----+-----+----------------------+---------------------+---------------------+-------------+
| 1 | 1 | 1 | 2019-11-03 19:08:06 | 2019-11-03 19:08:06 | NULL |
| 2 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 3 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 4 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 5 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 6 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 7 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 8 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 9 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 10 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 11 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 12 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 13 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 14 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 15 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 16 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 17 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 18 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 19 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 20 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 21 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 22 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 23 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 24 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 25 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 26 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 27 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 28 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 29 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 30 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 31 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 32 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 33 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 34 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
| 35 | 1 | 1 | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 | NULL |
+----+-----+----------------------+---------------------+---------------------+-------------+
35 rows in set (0.00 sec)
查看depot_store_depot_batch表情况,确实冻结了10个。
mysql> select * from `depot_store_depot_batch`;
+----+-----+------------+---------------------+---------------------+-------------+
| id | num | frozen_num | create_time | update_time | delete_time |
+----+-----+------------+---------------------+---------------------+-------------+
| 1 | 10 | 10 | 2019-11-03 19:06:59 | 2019-11-03 19:06:59 | NULL |
+----+-----+------------+---------------------+---------------------+-------------+
1 row in set (0.00 sec)
查看depot_store_depot_batch_frozen_record表情况,35row记录。
mysql> select * from depot_store_depot_batch_frozen_record;
+------+----------------------------+-------------------+------------------+------------+------+---------------------+---------------------+
| id | depot_store_depot_batch_id | before_frozen_num | after_frozen_num | frozen_num | desc | create_time | update_time |
+------+----------------------------+-------------------+------------------+------------+------+---------------------+---------------------+
| 2342 | 1 | 0 | 1 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2343 | 1 | 1 | 2 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2344 | 1 | 1 | 2 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2345 | 1 | 1 | 2 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2346 | 1 | 1 | 2 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2347 | 1 | 1 | 2 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2348 | 1 | 2 | 3 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2349 | 1 | 2 | 3 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2350 | 1 | 2 | 3 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2351 | 1 | 2 | 3 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2352 | 1 | 2 | 3 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2353 | 1 | 3 | 4 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2354 | 1 | 3 | 4 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2355 | 1 | 3 | 4 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2356 | 1 | 3 | 4 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2357 | 1 | 4 | 5 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2358 | 1 | 4 | 5 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2359 | 1 | 4 | 5 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2360 | 1 | 4 | 5 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2361 | 1 | 5 | 6 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2362 | 1 | 5 | 6 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2363 | 1 | 5 | 6 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2364 | 1 | 5 | 6 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2365 | 1 | 5 | 6 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2366 | 1 | 6 | 7 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2367 | 1 | 6 | 7 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2368 | 1 | 6 | 7 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2369 | 1 | 7 | 8 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2370 | 1 | 7 | 8 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2371 | 1 | 7 | 8 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2372 | 1 | 8 | 9 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2373 | 1 | 8 | 9 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2374 | 1 | 8 | 9 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2375 | 1 | 9 | 10 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
| 2376 | 1 | 9 | 10 | 1 | ???? | 2019-11-03 19:08:07 | 2019-11-03 19:08:07 |
+------+----------------------------+-------------------+------------------+------------+------+---------------------+---------------------+
35 rows in set (0.00 sec)
结论就是,虽然冻结数是对了,但是出了很多超卖的订单
加redis锁的代码
<?php
/**
* Created by PhpStorm.
* User: chunpat
* Date: 2019/11/2
* Time: 11:32 AM
*/
class Lock
{
private static $_instance ;
private $_redis;
private function __construct()
{
$this->_redis = new \Redis();
$this->_redis ->connect('127.0.0.1');
}
public static function getInstance()
{
if(self::$_instance instanceof self)
{
return self::$_instance;
}
return self::$_instance = new self();
}
/**
* 加锁
* @author: chunpat
* Date: 2019/11/2
* @param $key string 锁名称
* @param $expTTL int 多久过期,秒单位
*
* @return bool
*/
public function set($key,$expTTL)
{
//set 实现setnx 和 expire()的效果
$isLock = $this->_redis->set($key,time() + $expTTL ,['nx', 'ex'=>$expTTL]);
if($isLock)
{
return true;
}
return false;
}
/**
* @param $key string 解锁
*/
public function del($key)
{
$this->_redis->del($key);
}
}
$pdo = new PDO('mysql:host=127.0.0.1;dbname=store', 'root', '123456789');
//销售数量
$num = $_GET['num'] ?? 1;
//锁名
$lockName = 'store_depot_batch_lock';
try{
//加锁
$lock = Lock::getInstance();
//加锁失败抛出网络异常错误
if(!$lock->set($lockName,10)){
throw new RedisException('网络异常,请稍后再试');
}
//开启事务
$pdo->beginTransaction();
//查询门店仓库批次信息
$depotStoreDepotBatchSql="select * from `depot_store_depot_batch` where id =1 limit 1";
$depotStoreDepotBatchRes = $pdo->query($depotStoreDepotBatchSql)->fetch();
//操作后冻结数量
$afterFrozenNum = $num + $depotStoreDepotBatchRes['frozen_num'];
$activeNumber = $depotStoreDepotBatchRes['num'] - $afterFrozenNum;
if($activeNumber < 0){
throw new Exception('商品已售罄了');
}
//下单主表
$orderSql ="insert into `order` VALUES (null,{$num},1,NOW(),NOW(),null)";
$pdo->query($orderSql);
$orderId = $pdo->lastInsertId();
//下单是否成功判断
if(!$orderId){
throw new Exception('下单失败,请稍后再试');
}
//更新仓库
$depotStoreDepotBatchUpdateSql="update `depot_store_depot_batch` set `frozen_num`={$afterFrozenNum} WHERE id=1";
$pdo->query($depotStoreDepotBatchUpdateSql);
//冻结记录操作sql
$actionSql ="insert into `depot_store_depot_batch_frozen_record` VALUES (null,1,{$depotStoreDepotBatchRes['frozen_num']},{$afterFrozenNum},{$num},'并发测试',NOW(),NOW())";
$pdo->query($actionSql);
//提交事务
$pdo->commit();
//解锁
$lock->del($lockName);
echo '下单成功,订单id为' . $orderId;
} catch (\RedisException $e){
echo $e->getMessage();
} catch (\Exception $e){
//回滚事务
if($pdo->inTransaction()){
$pdo->rollBack();
}
//解锁
$lock->del($lockName);
echo $e->getMessage();
}
ab压力测试,ab -n 1000 -c 100 http://127.0.0.1:83/redis.php
~ ab -n 1000 -c 100 http://127.0.0.1:83/redis.php
This is ApacheBench, Version 2.3 <$Revision: 1826891 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.15.1
Server Hostname: 127.0.0.1
Server Port: 83
Document Path: /redis.php
Document Length: 25 bytes
Concurrency Level: 100
Time taken for tests: 2.508 seconds
Complete requests: 1000
Failed requests: 991
(Connect: 0, Receive: 0, Length: 991, Exceptions: 0)
Total transferred: 189001 bytes
HTML transferred: 27001 bytes
Requests per second: 398.65 [#/sec] (mean)
Time per request: 250.845 [ms] (mean)
Time per request: 2.508 [ms] (mean, across all concurrent requests)
Transfer rate: 73.58 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.8 0 4
Processing: 28 232 37.8 239 389
Waiting: 28 232 37.8 239 389
Total: 33 233 37.5 239 389
Percentage of the requests served within a certain time (ms)
50% 239
66% 248
75% 254
80% 258
90% 269
95% 284
98% 312
99% 320
100% 389 (longest request)
查看Order表情况,显示了10row order。
mysql> select * from `order`;
+----+-----+----------------------+---------------------+---------------------+-------------+
| id | num | store_depot_batch_id | create_time | update_time | delete_time |
+----+-----+----------------------+---------------------+---------------------+-------------+
| 1 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
| 2 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
| 3 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
| 4 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
| 5 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
| 6 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
| 7 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
| 8 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
| 9 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
| 10 | 1 | 1 | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 | NULL |
+----+-----+----------------------+---------------------+---------------------+-------------+
10 rows in set (0.00 sec)
查看depot_store_depot_batch表情况,确实冻结了10个。
mysql> select * from `depot_store_depot_batch`;
+----+-----+------------+---------------------+---------------------+-------------+
| id | num | frozen_num | create_time | update_time | delete_time |
+----+-----+------------+---------------------+---------------------+-------------+
| 1 | 10 | 10 | 2019-11-04 06:33:43 | 2019-11-04 06:33:43 | NULL |
+----+-----+------------+---------------------+---------------------+-------------+
1 row in set (0.01 sec)
查看depot_store_depot_batch_frozen_record表情况,10row记录。
mysql> select * from depot_store_depot_batch_frozen_record;
+----+----------------------------+-------------------+------------------+------------+------+---------------------+---------------------+
| id | depot_store_depot_batch_id | before_frozen_num | after_frozen_num | frozen_num | desc | create_time | update_time |
+----+----------------------------+-------------------+------------------+------------+------+---------------------+---------------------+
| 1 | 1 | 0 | 1 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
| 2 | 1 | 1 | 2 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
| 3 | 1 | 2 | 3 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
| 4 | 1 | 3 | 4 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
| 5 | 1 | 4 | 5 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
| 6 | 1 | 5 | 6 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
| 7 | 1 | 6 | 7 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
| 8 | 1 | 7 | 8 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
| 9 | 1 | 8 | 9 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
| 10 | 1 | 9 | 10 | 1 | ???? | 2019-11-04 06:34:40 | 2019-11-04 06:34:40 |
+----+----------------------------+-------------------+------------------+------------+------+---------------------+---------------------+
10 rows in set (0.00 sec)
结论就是,我加大的压力测试,结果也是我们想要的
注意与疑惑
注意:
- 1、要用多进程的php-fpm测试,不能用单进程的cli。
疑惑:
- 1、在redis set 10秒过期后,糟糕情况就是程序还没执行完成set过期了,导致超卖现象。
参考
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 chunpat 及本文源链接。