Redis的原子性解决并发问题

Posted by chunpat on November 2, 2019

问题概述

最近根据运营那边提供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过期了,导致超卖现象。

参考


Creative Commons License
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 chunpat 及本文源链接。