高并发下投标过程进行优化

来源:互联网 发布:知乎手机端进不去 编辑:程序博客网 时间:2024/05/16 13:42

业务流程


对于一个融资标的invest表, 标的id,标的总融资金额(total_money), 已投资金额(invested_money),满标时间(finish_invest_time),标的状态(status)

假如有多个用户user同时投标,投资金额为M,  为保证数据一致性,以下步聚在同一个事务当中

1.  查询left = total_money - invested_money, 如果left <=0, 则不可投, 如果M > left, 则提示投资金额不能大于剩余可投金额

2. 查询用户资金余额balance, 如果balance<M, 则提示用户账户余额不足请先充值

3. int rows = update user表set balance = balance - M where id = ? and balance - M >=0,如果rows=0,则回滚

4. 插入记录到已投资列表表中insert into invest_list表

5. int rows = update invest表 set invested_money = invested_money + M where id = ? and invested_money + M <= total_money, 如果rows=0则事务回滚

6. 查询left = total_money - invested_money,如果left=0,则更改状态status为'还款中',满标时间为当前时间

7.给用户发送短信或邮件提示投标成功


如果按照此事务流程,系统最容易堵塞在步骤5中,系统的并发度比较低, 所以计划采用异步队列的方式

 将标的id,和可投资金额left=total_money - invested_money保存在内存ConcurrentHashMap中, 当用户投资金额M时, left = left - M,如果left> 0时,表示可投,则分出一个线程并在同一个事务中用来执行如下操作

1. 查询用户资金余额balance, 如果balance<M, 则提示用户账户余额不足请先充值,并将map中left加回M

2. int rows = update user表set balance = balance - M where id = ? and balance - M >=0,如果rows=0,则回滚并将map中left加回M

3. 插入记录到已投资列表表中insert into invest_list表,并将该用户投资记录放到一个queue中去

4. 从queue中取出该用户投资记录,并异步执行上一个事务的5、6、7步聚


总结, 想方设法将单事务任务转变成多线程任务来执行, 使用消息队列来达到最终一致性



0 0