- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
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个.
然后,我们使用ab工具来模拟1000次请求,50并发量来测试 。
1
|
ab -n 1000 -c 50 www.test.com/
|
然后我们通过redis desktop manager来查看一些redis的结果 。
couponorder队列里已经有了10个用户的信息了 。
并且优惠券的剩余数量也是0了,不再是负数了 。
同时,用户抢券集合里也保存了10个用户的uid信息.
上面这串代码解决了两个问题:
但是,这段代码也存在一定的问题
提示:在消费队列里,如果优惠券发放失败,一定要立即记录并短信通知运营管理人员,看看是否能重发或者通过后台手动定向推送给用户.
所以,后续我又使用了lua脚本和redis配合一起来解决了这个问题。具体代码,我会后续整理处理补充完整.
总结 。
到此这篇关于php+redis事务解决高并发下商品超卖问题的文章就介绍到这了,更多相关php redis 解决高并发下商品超卖内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://www.cnblogs.com/itbsl/archive/2020/08/02/13418176.html 。
最后此篇关于PHP+Redis事务解决高并发下商品超卖问题(推荐)的文章就讲到这里了,如果你想了解更多关于PHP+Redis事务解决高并发下商品超卖问题(推荐)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试在多线程环境中实现某种累积逻辑;我想知道没有 lock 和 synchronized 关键字是否有更好/更快的方法来做到这一点?以下是我当前的代码: public class Concurr
我需要帮助构建一个实现信号量的监视器,简单的 C 示例就可以。 这是为了证明可以在任何可以使用信号量的地方使用监视器。 最佳答案 如果您说允许使用互斥锁/condvars,请检查: #include
我已经构建了一些返回部分产品目录的 ajax,并且我正在尝试将 xml 输出到文档中,到目前为止,这是我所拥有的: $("#catalog").append("Item NamePriceDe
很抱歉,如果我的问题之前已经被问过,或者它太明显了,但我真的需要澄清这一点。感谢您的帮助。 在多用户界面中,如果来自不同用户的相同事务同时到达服务器,会发生什么? 我有下一张表: create tab
这可能是一个愚蠢的问题,但是这个程序的输出(它的方式)可以为零吗? public class Test2{ int a = 0; AtomicInteger b = new Atomi
假设我本地主机上的一个网站处理每个请求大约需要 3 秒。这很好,正如预期的那样(因为它在幕后进行了一些奇特的网络)。 但是,如果我在选项卡(在 firefox 中)中打开相同的 url,然后同时重新加
我对 MongoDB 的读锁定有点困惑。单个集合可以支持多少个并发读取操作? 最佳答案 如 tk 给出的链接中所写:http://www.mongodb.org/pages/viewpage.acti
如果有四个并发的 CUDA 应用程序在一个 GPU 中竞争资源会发生什么这样他们就可以将工作卸载到图形卡上了? Cuda Programming Guide 3.1 提到那里 某些方法是异步的: 内核
👊上次的百度面试遇到了关于spark的并发数的问题,今天我们就来将这些问题都一并解决一下,图画的的有点丑,还行大家见谅,百度实习的问题我放在了下面的链接👇: 链接: 2022百度大数据开发工程师实
我对 Groovy 线程有疑问。 我的任务是以某种方式翻译给定目录中的每个文件 并将生成的输出放在其他目录中的文件中。 我编写了以下代码,该代码有效: static def translateDir(
Java中的同步和锁定有什么区别? 最佳答案 synchronized是语言关键字;锁是对象。 当一个方法或代码块被标记为同步时,您是说该方法或代码块必须先获得某个锁对象(可以在同步的语法中指定)才能
我需要创建一个能够同时处理来自客户端的多个请求的并发 RPC 服务器。 使用 rpcgen linux编译器(基于sun RPC),不支持-A为并发服务器创建 stub 的选项。 (-A 选项在 so
System.out.println("Enter the number of what you would like to do"); System.out.println("1 = Manuall
我正在将我的应用程序移植到 iOS 8.0 并注意到 UIAlertView 已被弃用。 所以我改变了使用 UIAlertController 的方法。这在大多数情况下都有效。 除了,当我的应用程序打
我正在逐行同时读取两个文本文件。 我特别想做的是当lineCount在每个线程上都是相同的我想看看扫描仪当前正在读取的字符串。 我环顾四周寻找可以实现的某些模式,例如 Compare and Swap
我正在阅读 Java Concurrency in Practice .在章节中断政策部分 取消和关闭 它提到 A task should not assume anything about the
我正在尝试学习线程,互斥等的基础知识。遵循here的文档和示例。在下面的代码中,我得到预期的输出。问题: 想确认我是否有任何陷阱?我们如何改善下面的代码? 我的线程在哪一行尝试获取互斥锁或正在等待互斥
并发是指两个任务在不同的线程上并行运行。但是,异步方法并行运行,但在同一个线程上。这是如何实现的?另外,并行性怎么样? 这三个概念有什么区别? 最佳答案 并发和并行实际上与您正确推测的原理相同,两者都
以此ConcurrentDouble类定义为例: public class ConcurrentDouble { public double num = 0; public void subt
在得知并发确实增加了许多人的吞吐量后,我一直计划在项目中使用并发。现在我在多线程或并发方面还没有做太多工作,因此决定在实际项目中使用它之前学习并进行简单的概念验证。 以下是我尝试过的两个示例: 1.
我是一名优秀的程序员,十分优秀!