乐观锁、悲观锁、数据库行锁 RPC调用的幂【面试题详解】

今天爱分享给大家带来乐观锁、悲观锁、数据库行锁 RPC调用的幂【面试题详解】,希望能够帮助到大家。

先说结论:建议优先用数据库行锁的做法更新额度。mysql数据库的tps我了解到的一个值是4000,大部分场景是满足的。各应用的真实情况还需要自行再压测。不建议刚开始就引入redis等中间件增加复杂度。

以下主要讨论:乐观锁、悲观锁、数据库行锁。RPC调用的幂等问题

数据库行锁(建议):通过where 条件限制不会超额或者超卖


// 其中seq=#{seq}的seq指额表记录的业务主键:在根据个人限额的场景下可能是身份证信息或者卡号;在根据产品限额的场景下可能就是产品码
String sql="update limit_info set avai_amount= avai_amount - #{current}  
where seq=#{seq} and avai_amount > #{current}";
int res = excute(sql);
//根据影响的行数,res是0还是1判断更新是否成功



以下列举下悲观锁及乐观锁的写法以及可能存在的问题

悲观锁:select…for update。缺点:性能会有所下降,大部分业务场景不需要悲观锁。


 //开启事务
 begin();
 Bigdecimal avaiAmount = excute("select avai_amount from limit where id=#{id} for update");
 Bigdecimal newAvaiAmount = avaiAmount - current;
//判断余额是否足够
//更新余额
if(newAvaiAmount.compareTo(BigDecimal.ZERO) >= 0){
   int res = excute("update limit_info set avai_amount=#{newAvaiAmount}  where id=#{id}");
}
commit();



乐观锁:update时添加条件avai_amount=#{avaiAmount}。缺点:要有重试机制,增加了代码复杂度。


Bigdecimal avaiAmount = excute("select avai_amount from limit_info where id=#{id}");
Bigdecimal newAvaiAmount = avaiAmount - current;
//判断余额是否足够
//更新余额
if(newAvaiAmount.compareTo(BigDecimal.ZERO) >= 0){
   int res = excute("update limit_info set avai_amount=#{newAvaiAmount}  
   where id=#{id} and avai_amount=#{avaiAmount}");
}



ps: 互金理财应用里关于按天控制额度用sql的写法(基金生产在用的做了简化):


--冻结客户交易份额
update LIMIT_INFO
set USED_AMT = CASE WHEN WORK_DATE = #workDate# 
then USED_AMT + #usedAmt# else #usedAmt# end,
WORK_DATE = #wokdDate#,
MAX_AMT = #maxAmt#,
where CST_NO = #cstNo#
AND CASE WHEN WORK_DATE = #workDate# 
then USED_AMT + #usedAmt# 
else #usedAmt# end <= MAX_AMT
--回滚已使用额度
update LIMIT_INFO
SET USED_AMT = CASE WHEN WORK_DATE = #workDate# 
then USED_AMT - #usedAmt# else 0 end, 
WORK_DATE = #workDate#,
WHERE CST_NO = #cstNo#
AND WORK_DATE <= #workDate# 
 AND (CASE WHEN WORK_DATE = #workDate# 
 then USED_AMT - #usedAmt# else 0 end) >= 0



人已赞赏
数据库

This function has none of DETERMINISTIC NO SQL,or READS SQL DATA in it【解决方法】

2020-12-13 13:11:35

数据库

查询判重在并发下存在的问题 交易判重 数据库底层判重【附代码】

2020-12-23 14:32:48