V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  liangliplusss  ›  全部回复第 1 页 / 共 1 页
回复总数  1
25 天前
回复了 hhhhhh123 创建的主题 程序员 高并发下怎么做余额扣减?
两个方案
方案一: 悲观锁
consume(var accountId,var amount) {
//先查询余额
"select accountId,balance from xxx where accountId = $accountId for update";
//计算
$new_balance = $old_balance - $amount;
update xxx balance = $new_balance where accountId = $accountId
}

方案二: 乐观锁
consume(var accountId,var amount) {
flag = false,retires = 3
// CAS + 重试
while(!flag && retries > 0) {
flag = consume0(accountId,amount);
retries--;
}

}

boolean consume0(var accountId,var amount) {
//先查询余额(只是查询不加锁)
"select accountId,balance from xxx where accountId = $accountId";
//计算
$new_balance = $old_balance - $amount;
row = update xxx balance = $new_balance where accountId = $accountId and balance = $old_balance
return row == 1;
}

备选方案:(高并发,单个用户消费并发超过 1000 )缓存 + 消息中间件,
用户消费操作是扣减缓存中余额(注意这里原子性查询和扣减两个动作,例如 redis 可以使用 lua ), 扣减成功发送消息到消息队列更新数据库。
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2735 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 9ms · UTC 12:25 · PVG 20:25 · LAX 04:25 · JFK 07:25
Developed with CodeLauncher
♥ Do have faith in what you're doing.