nuomiphp
正在加载…
请使用更现代的浏览器并启用 JavaScript 以获得最佳浏览体验。
加载论坛时出错,请强制刷新页面重试。
高并发下怎么做余额扣减?
hhhhhh123
Jooooooooo
那库存这种问题 应该怎么解决?
Jooooooooo
hhhhhh123
库存的高并发扣减算是比较成熟的东西了, 随便一搜很多的比如可以搞多层拦截, 如果你只卖 10 个东西, 要是有 1w 人来抢, 那绝大多数流量没有必要到后端, 反正总是能把东西卖出去的. 前端和网关可以直接随机丢弃流量, 流量到了后端后, 可以再加上 MQ 排队和缓存, 最终再到数据库里行锁扣库存.还有手段比如把库存分散到多行数据上, 随机挑一行扣
brust
hhhhhh123
#8库存的话如果是热点 SKU 可以分段锁 比如有 1w 个库存 可以分成 10 个 1000 出来
ElmerZhang
如果并发不会很高的话不用在数据库上加锁
1. 要扣的钱为 A ,先查 amount 当前值为 B ,代码中判断 B >= A
2. 然后执行 update xxx set amount = amount - A where amount = B
3. 执行看影响行数,如果为 0 ,重新从第 1 步执行
一般只需要重试一次。
CEBBCAT
ElmerZhang
dongtingyue
coderxy
看三位的回答中好像没有提到事务,不用事务的话遇到意外停机怎么办呢?或者是我理解错了
8520ccc
ElmerZhang
update xxx set amount = amount - A where amount = B where amount-A>0
codehz
ElmerZhang
那不如直接 update xxx set amount = amount - A where amount > A (
hhhhhh123
ElmerZhang
我理解 第一步和第二步 ,第三部不是特别理解, 为啥只递归一次?
dongtingyue
update xxxxx set xxxx where 余额>xx 余额 用 innodb 本身就有行锁,失败返回异常,这点时间肯定要等的
coderxy
乐观锁就够了,修改时判断一下余额与你之前查到的余额是否一致。
git00ll
一锁 二查 三更新
jobmailcn
CEBBCAT
同时更新多个才要事务,例如给一个人加余额,另一个人减余额。
CEBBCAT
jobmailcn
是的。我看楼主这个 case 就是需要一边扣钱,一边发放什么东西。
awanganddong
https://www.51cto.com/article/720873.html
并发扣款,如何保证一致性
沈剑 大佬的文章可以看看
richangfan
update users set balance = balance - 1 where user_id = 123 and balance >= 1;
只在余额大于 1 时扣除用户 123 的 1 块钱
orzwalker111
richangfan
假设网关、框架重试,会多扣款,解决手段:1 、悲观锁,使用分布式锁2 、乐观锁,使用 CAS ,select 得到的 balance 作为 update 的 where 条件,并添加 ver 条件解决 ABA 问题
hhhhhh123
vanillacloud
codehz
8520ccc
richangfan
如果这样的话, 同时有俩个 一个扣款 10 块 一个扣款 5 块。 这样只会执行其中的一个余额。 另外一个就不会执行。 我觉得 8 楼的 第三个条件挺好, 但是递归次数 又不好拿捏。
louisliu813
orzwalker111
是的,我们也是使用 cas ,更新时判断 version ,如果被其他事物更新到 version + 1 了,就 select 新的 balance 和 version 出来,然后基于新 version 做判断,新 balance 做更新。
xuanbg
不要做无意义的事情,15 楼的方法可以很好的解决 OP 你的这个问题。
rqrq
try {
BEGIN;
SELECT balance FROM userinfo WHERE user_id = xxx FOR UPDATE;
逻辑判断,有问题就 throw Exception
UPDATE userinfo...
COMIT;
} catch {
ROLLBACK;
}
rqrq
BEGIN 写在 try 外面。
yogogo
事务加行锁,扣款交易可以先入库,再用异步任务按顺序执行交易扣款。有些第三方代扣服务就是这样设计的
dingyaguang117
乐观锁即可
reeco
实操都是 tcc ,两步提交
下一页 »