您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
redis乐观锁解决超卖超买问题
发布时间:2021-09-19 16:30:40编辑:雪饮阅读()
在前篇https://www.gaojiupan.cn/manshenghuo/chengxurensheng/4010.html中用mysql中的悲观锁解决了超卖超买的情况,那么悲观锁毕竟性能消耗巨大。
那么接下来需要给我们的php安装上redis扩展,比如我这里下载的是
php_redis-2.2.7-5.4-ts-vc9-x86.zip
解压后将php_redis.dll放到ext目录并且在php.ini中添加这个php_redis.dll扩展
D:\phpstudy_pro\Extensions\php\php-5.4.45-Win32-VC9-x86>php.exe -m
[PHP Modules]
bcmath
calendar
Core
ctype
date
dom
ereg
filter
ftp
hash
iconv
json
libxml
mcrypt
mhash
mysql
mysqlnd
odbc
pcre
PDO
Phar
pthreads
redis
Reflection
session
SimpleXML
SPL
standard
tokenizer
wddx
xml
xmlreader
xmlwriter
zip
zlib
[Zend Modules]
扩展安装好后我们将之前超卖超买的那个问题再以redis的解决方案则如:
demo2.php:
<?php
error_reporting(E_ALL ^ E_DEPRECATED);
class Conf {
public static $host = '192.168.43.170';
}
//利用redis事务实现乐观锁
class OptimisticLock extends Thread {
public function run() {
$redis = new Redis();
$redis->connect(Conf::$host);
do {//只要还有库存且没成功减库存就一直执行
$goodsTotal = $redis->get('goods_total');
echo self::getCurrentThreadId().' total='.$goodsTotal."\n";
if($goodsTotal <= 0) break;//每次都检查是否还有库存 没有库存退出循环
//Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
$redis->watch('goods_total');
$redis->multi();
//Multi 命令用于标记一个事务块的开始。
//事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行。
$redis->decr('goods_total');
//Exec :
//命令用于执行所有事务块内的命令。
//返回值,事务块内所有命令的返回值,按命令执行的先后顺序排列。 当操作被打断时,返回空值
$res = $redis->exec();
} while(!$res);
}
}
//初始化缓存库存数据
$redis = new Redis();
$redis->connect(Conf::$host);
$redis->set('goods_total',100);
$clientArr = [];
for ($i=0;$i<100;++$i) {
$clientArr[$i] = new OptimisticLock();
$clientArr[$i]->start();
}
那么这样跑一次后
D:\phpstudy_pro\Extensions\php\php-5.4.45-Win32-VC9-x86>php.exe D:\phpstudy_pro\blog\public\demo2.php
20776 total=100
14324 total=99
22144 total=99
22144 total=98
21460 total=97
21896 total=97
21348 total=97
21868 total=97
20768 total=97
20372 total=96
8676 total=96
20720 total=96
21460 total=96
21348 total=96
20768 total=95
………………………..
……………………….
你会发现库存正好为0了。
这段代码使劲多次执行,最后库存也是0,所以也是可行的,这个方法也是首先推荐的方法,内存中的数据操作比在数据库中要快得多,负载能力会高跟多。
本分享给出的示例代码只是处理逻辑,具体应用还要根据具体服务器架构甚至是业务逻辑进行调整。有不足之处欢迎批评指正。
关键字词:redis,乐观锁,超卖超买
下一篇:phpunit基境-setUp