redis mysql 解决超卖_Redis 并发防止超卖

那么,既然“下单减库存”和“付款减库存”都有缺点,我们能否把两者相结合,将两次操作进行前后关联起来,下单时先预扣,在规定时间内不付款再释放库存,即采用“预扣库存”这种方式呢?

这种方案确实可以在一定程度上缓解上面的问题。但是否就彻底解决了呢?其实没有!针对恶意下单这种情况,虽然把有效的付款时间设置为10分钟,但是恶意买家完全可以在10分钟后再次下单,或者采用一次下单很多件的方式把库存减完。针对这种情况,解决办法还是要结合安全和反作弊的措施来制止。

加锁set是为了防止多机用户同时访问同一共享资源,即库存数。

1.先扣减库存,防止用户抢购后未支付

2.定时任务扫描5分钟内未支付订单,并主动请求支付状态

3.关闭订单,重新释放库存

/**

* Created by PhpStorm.

* User: Administrator

* Date: 2020/7/7

* Time: 17:09

*/

//连接本地的 Redis 服务

/* Connect to an ODBC database using driver invocation */

$dsn = 'mysql:dbname=homestead;host=192.168.10.10';

$user = 'homestead';

$password = 'secret';

$redis = new Redis();

$redis->connect('127.0.0.1', 6379);

//存储数据到列表中

//for($i=0;$i<=10;$i++){

// $redis->lpush("goods_store",1);

//}

//var_dump($redis->lLen("goods_store"));

//exit;

$rand_num = rand(1,10);

//$rand_num =1;

//库存获取

$key = 'lock';

$random = rand(0,1000);

$ttl = time();

//NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。

//EX second :设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。

$rs = $redis->set($key, $random, array('nx', 'ex' => $ttl));

if ($rs) {

//处理更新缓存逻辑

$Len = $redis->lLen("goods_store");

//判断库存

if($Len >= $rand_num){

//生成订单数据

//....

//下面这一段属于支付成功后执行,这样可以防止有些抢购了未支付情况

try {

$dbh = new PDO($dsn, $user, $password);

$dbh->beginTransaction();

$sql = "UPDATE `Course` SET `order_number`=order_number-$rand_num WHERE (`c_id`='03')";

$sth = $dbh->exec($sql);

$dbh->commit();

// 获取存储的数据并输出

for($i=1;$i<=$rand_num;$i++){

$arList = $redis->lpop("goods_store");

}

var_dump($redis->lLen("goods_store"),$arList);

} catch (PDOException $e) {

echo 'Connection failed: ' . $e->getMessage();

}

}

//先判断随机数,是同一个则删除锁

if ($redis->get($key) == $random) {

$redis->del($key);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值