6 回答
TA贡献1875条经验 获得超3个赞
你说的订单问题,其实是:高并发场景下,如何正确扣减库存的问题if($b>=0)
这样的判断,在高并发的场景下并不使用,因为这样的业务逻辑判断并不是 原子操作
,所以存在 脏读
的可能。
例如:
由两个请求同时到达
服务端
(分别名为:p1
,p2
),p1
先取到了数据,走到了if
判断,
此时p2
也取到了数据,但是p1
还没有更新数据库,所以p2
取到的数据跟p1
是一样的,所以,p1
p2
得到的$b
值是一样的,p2
也可以通过if
条件,但是这两个请求只扣减了一次存库。
如何解决这个问题呢?
加锁;
队列:改并行为串行,依次扣减;
操作转换为原子操作;
不光是数据库操作,高并发场景下,还可能会面对什么问题呢:
单点问题(当然 非刚并发场景也会面临这个问题,但是高并发场景,此问题尤为突出)
最大连接数问题,eg.
web 服务器
数据库
...数据安全问题,eg.
脏读
重复操作
TA贡献1789条经验 获得超10个赞
1、将字段设置为UNSIGNED,然后基础sql如 set a=a-1 where a>0,不要先读出来,然后再操作,可以在一定程度上减少你的并发为负数的可能
2、串行化操作,比如使用redis队列
3、使用redis或者别的原子递增模拟锁操作,比如 incr("lock") == 1 { 进行减操作; 删除lock)} else 自旋,直到得到锁进行以上操作,或者超时
基本上php解决如上问题的思路!!
TA贡献1998条经验 获得超6个赞
这类需求主要还是讲逻辑的严密性
而非并发时的情形
!
你可能看到了所谓的if
,但忽略了数据库
的重要性.
比如下单
是一个从订单状态
到库存状态
的过程.
那么下单
这个过程生成肯定会涉及order_id
的唯一性,
此时是否并发
就不再重要,数据的唯一性
才是最重要的.
而此后,才是你的所谓if
减库存过程.
TA贡献1859条经验 获得超6个赞
实际中可能是这样的,你的$a是查询出来的对吧,有可能在高并发的场景下你走了if判断但是没有改变库存的情况下,其他请求已经在读数据了,这个时候你读到的$a就是没减少库存时候的状态。这只是其中一点,最可怕的是如果你用的mysql数据库,查询和修改都会加锁在并发很高的情况下可能会把表直接锁死,其他的操作在等待中,一旦等待执行时间过长、执行过多,数据库就挂掉了。还有你这个测试1000并发的时候使用的代码并不是实际业务中的代码,因为如果减库存这种操作,肯定会有很多相关的逻辑判断,1000个并发执行起来就没你想象的这么完美了。
- 6 回答
- 0 关注
- 472 浏览
添加回答
举报