最近遇到一些简单并发问题的记录

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最近遇到一些简单并发问题的记录相关的知识,希望对你有一定的参考价值。

1. 程序代码加锁,可以用JAVA.concurrent.包下的Lock类,比如营销系统的记账流水,详细可参见这块的代码...........


2. 清结算系统接口定时任务批量通知X变现更新用户的变现资产,同一个人多比变现会更新出现脏数据,采用行级索就能解决

<!-- 成功变现后更新用户的成功变现金额和成功变现后的剩余资产 -->
<update id="updateSuccedAssetsByFpOrderId" parameterType="com.***.***.p2p.domain.loan.BxdLoan" >
update bxd_mem_assert 
set 
succed_bx_money = succed_bx_money + #{bxMoney,jdbcType=DECIMAL},
succed_surplus_assets = succed_surplus_assets - #{bxMoney,jdbcType=DECIMAL} - #{bxInterests,jdbcType=DECIMAL},
update_time = now()
where fp_order_id = #{fpOrderId,jdbcType=VARCHAR}
</update>
<!-- 取消变现、流标/取消放款后的资金回退,恢复用户的变现前的变现金额和剩余资产 -->
<update id="updateRollbackAssetsByFpOrderId" parameterType="com.***.***.p2p.domain.loan.BxdLoan" >
update bxd_mem_assert 
set 
bx_money = bx_money - #{bxMoney,jdbcType=DECIMAL},
surplus_assets = surplus_assets + #{bxMoney,jdbcType=DECIMAL} + #{bxInterests,jdbcType=DECIMAL},
update_time = now()
where fp_order_id = #{fpOrderId,jdbcType=VARCHAR}
and bx_money > 0
</update>

 

3.借款人在点取消变现的同时,用户在产品详情页点了下单按钮,主要是前端页面停顿到提交到后台业务逻辑处理的时差问题导致的。需要双向控制:
1)在更新变现单状态为‘已取消’时,需要先检测是否存在订单,采用update status where exists select order
2)在用户下单的后台逻辑里,要先检查是否用户已经取消了变现,即此产品是否还处于在售中的状态,虽然用户一开始看到的是在售中,通过此状态链接进入了购买页面,但是下单之前可能已经被改掉了。

<!-- 
取消变现: 更新产品状态为:已取消,程序后续还要更新变现单状态为“取消变现”
通过行级索方式控制
可取消条件:在售中的变现单、且此变现单不存在有效地投资的订单(除状态为3交易取消,8交易关闭之外的订单都认为为有效订单)
-->
<update id="updateForCancelByProductId" parameterType="java.lang.String" >
UPDATE 
bxd_prd_base prd 
SET
prd.status_code = ‘12‘,
prd.status_value = ‘已取消‘ 
WHERE EXISTS 
( SELECT 
bl.loan_id FROM bxd_loan bl 
WHERE bl.del_flag = 0 
AND bl.loan_id = #{productId,jdbcType=VARCHAR}
AND bl.status_code = 1 
AND bl.loan_id = prd.product_id 
AND NOT EXISTS 
(SELECT 
bod.product_id 
FROM
bxd_ord_detail bod 
WHERE bl.loan_id = bod.product_id 
AND bod.status_code NOT IN (3, 8))
)
</update>

 

4. XXX宝申购,或者前台表单提交没有防重,或者由于网络的问题,导致一个请求到后台变成了2此接口请请求 ,导入用户一个x变现订单同时申购了两次。
解决办法:
1) 前端:加上防重机制:如var submitLock=false;,并且如果是$.ajax的话,设置成同步,不要异步!
2) 后端:控制器通过Token控制
3) 数据库层每次insert前都要确保没有相同的流水插入过,通过在流水号字段加唯一索引,保证同一个业务只插一条记录,并且根据insert的返回值进行下一步操作!或者直接通过下面的语句:

INSERT INTO `bxd_tnb_trade_wait` (`account_no`, `order_id`, `trade_money`, `status_code`, `record_count`, `add_time`, `update_time`, `del_flag`) 
SELECT ‘6976870‘,‘601000284‘,‘9999999‘,‘9‘,‘9‘,‘20169-09-19 19:59:09‘,‘2019-09-19 19:59:09‘,‘0‘ FROM DUAL
WHERE NOT EXISTS (SELECT order_id FROM bxd_tnb_trade_wait WHERE order_id=‘601000233‘)

 

以上是关于最近遇到一些简单并发问题的记录的主要内容,如果未能解决你的问题,请参考以下文章

记录最近深圳面试的所遇到的面试题

创建自己的代码片段(CodeSnippet)

最近学习redis一些简单的记录

提效小技巧——记录那些不常用的代码片段

如何在 Vs Code 中更改默认自动选择的用户片段行为

动手造轮子:实现简单的 EventQueue