gpt4 book ai didi

PHP+Redis事务解决高并发下商品超卖问题(推荐)

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 33 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章PHP+Redis事务解决高并发下商品超卖问题(推荐)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

对于一些有一定用户量的电商网站,如果只是单纯的使用关系型数据库(如mysql、oracle)来做抢购,对数据库的压力是非常大的,而且如果不使用好数据库的锁机制,还会导致商品、优惠券超卖的问题。我所在的公司也遇到了同样的问题,问题发生在优惠券被超量抢购上,在问题发生后我们开始想办法解决问题,由于自己使用redis比较多,我准备使用redis来解决这个问题。利用redis的高性能和事务特性来解决线上优惠券被超库存抢购的问题,下面我给出我临时解决这个问题的第一版的伪代码,去掉了一些细节:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
  * 抢优惠券(秒杀)
  * @param int $couponid 商品id
  * @param int $uid 用户id
  * @return bool
  */
function seckill( $couponid , $uid )
{
  //1.初始化redis连接
  $redis = new redis();
  if (! $redis ->connect( '127.0.0.1' , 6379)) {
  trigger_error( 'redis连接出错!!!' , e_user_error);
  } else {
  echo '连接正常<br>' ;
  }
 
  //秒杀商品的库存key
  $key = 'seckill:' . $couponid . ':stock' ;
  $redis ->watch( $key );
 
  //获取库存
  $stock = $redis ->get( $key );
 
  //秒杀未开始,表示库存为null
  if (! $stock && ! is_numeric ( $stock )) {
  echo '秒杀未开始' ;
  return false;
  }
 
  //判断库存,如果库存大于0,则减库存,将该成功秒杀用户加入哈希表,如果小于等于0,秒杀结束
  if ( $stock <= 0) {
  echo '秒杀已结束' ;
  return false;
  }
 
  //用户已经成功秒杀过一次了,不允许再次参与秒杀
  if ( $redis ->sismember( 'seckill:' . $couponid . ':uid' , $uid )) {
  echo '秒杀失败' ;
  return false;
  }
 
  //代码走到这里,说明该用户是第一次参与秒杀,将库存减一,然后把这个人放到已抢到的集合表
  //multi(),返回一个redis对象,并进入multi-mode模式,一旦进入multi-mode模式,以后调用的所有方法都会返回相同的对象,
  //直到exec()方法被调用。
  $result = $redis ->multi()->decr( $key )->sadd( 'seckill:' . $couponid . ':uid' , $uid )-> exec ();
 
  if ( empty ( $result )) { //事务被取消
  echo '秒杀失败' ;
  return false;
  }
 
  //抢券成功,将优惠券id和uid放入到队列中,由一个单独的进程队列来消费队列里的数据,向用户推送抢到的优惠券
  $redis ->lpush( 'couponorder' , $couponid . '+' . $uid );
 
  $redis ->close();
  return true;
}
 
$couponid = 11211;
$uid = mt_rand(1, 100);
seckill( $couponid , $uid );

首先,我模拟设置优惠券id为11211的优惠券库存为10个.

PHP+Redis事务解决高并发下商品超卖问题(推荐)

然后,我们使用ab工具来模拟1000次请求,50并发量来测试 。

?
1
ab -n 1000 -c 50 www.test.com/

然后我们通过redis desktop manager来查看一些redis的结果 。

couponorder队列里已经有了10个用户的信息了 。

PHP+Redis事务解决高并发下商品超卖问题(推荐)

并且优惠券的剩余数量也是0了,不再是负数了 。

PHP+Redis事务解决高并发下商品超卖问题(推荐)

同时,用户抢券集合里也保存了10个用户的uid信息.

PHP+Redis事务解决高并发下商品超卖问题(推荐)

上面这串代码解决了两个问题:

  • 解决了瞬时的大量查询到数据库上给数据库造成很大压力的问题,流量都被拦截在了redis缓存层
  • 解决了优惠券被超库存抢购的问题

但是,这段代码也存在一定的问题

  1. 没有使用redis连接池,频繁创建新的redis有一定的性能影响
  2. 由于使用了事务,每一次并发请求中只会有一个用户抢券成功,该并发请求中的其它用户都会失败,只能等第二次并发
  3. 同样还是事务导致的库存遗留问题,如果有10个商品,1000次请求每次200并发量,5次并发请求就完成了1000次请求,但是只会有5个用户成功抢到,如果没有后续的请求,会导致库存还有5份存量

提示:在消费队列里,如果优惠券发放失败,一定要立即记录并短信通知运营管理人员,看看是否能重发或者通过后台手动定向推送给用户.

所以,后续我又使用了lua脚本和redis配合一起来解决了这个问题。具体代码,我会后续整理处理补充完整.

总结 。

到此这篇关于php+redis事务解决高并发下商品超卖问题的文章就介绍到这了,更多相关php redis 解决高并发下商品超卖内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。

原文链接:https://www.cnblogs.com/itbsl/archive/2020/08/02/13418176.html 。

最后此篇关于PHP+Redis事务解决高并发下商品超卖问题(推荐)的文章就讲到这里了,如果你想了解更多关于PHP+Redis事务解决高并发下商品超卖问题(推荐)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com