Springboot解决业务并发问题

一、业务需求(大家有类似的也可以参考我的解决方案)

实现一种类似于医院预约的预约功能,在同一个时间段,可能大家都看得到这个预约的按钮,大家都点进去了,这个时候真正提交预约信息的时候,就会可能出现多个请求同一个时间段的预约,在service层中,有可能会造成并发问题:几个线程可能都读到时间段的status(数据库中字段)为1,大家都能提交预约了

二、解决方案

方案一:select for update + @Transactional

在对应的service层方法中加上这个注解,手动开启事务,这会导致我们这个方法全部执行完毕之后,才会进行事务的提交,不然则不会提交事务,途中如果有异常,则会rollback,出现状态码500

select for update 这句话会将数据库查到的数据进行加上悲观锁(查到多少就加多少行的锁,会导致更大的问题,大家请精确到一行数据进行加锁),加上锁之后,其他线程想要执行这条语句的时候就会被阻塞的

什么时候会释放锁呢?要等到我们这个方法完成了,事务提交了就会进行释放锁(正常情况下)

这里简单跟大家说select for update加的行级锁知识和该注解的知识

select for update:

for update是一种行级锁,又叫排它锁,一旦用户对某个行施加了行级加锁,则该用户可以查询也可以更新被加锁的数据行,其它用户只能查询但不能更新被加锁的数据行.如果其它用户想更新该表中的数据行,则也必须对该表施加行级锁.即使多个用户对一个表均使用了共享更新,但也不允许两个事务同时对一个表进行更新,真正对表进行更新时,是以独占方式锁表,一直到提交或复原该事务为止。行锁永远是独占方式锁。

只有当出现如下之一的条件,才会释放共享更新锁:
1、执行提交(COMMIT)语句
2、退出数据库(LOG OFF)
3、程序停止运行

@Transactional:

实现原理:
 
1) 事务开始时,通过AOP机制,生成一个代理connection对象,
   并将其放入 DataSource 实例的某个与 DataSourceTransactionManager 相关的某处容器中。
   在接下来的整个事务中,客户代码都应该使用该 connection 连接数据库,
   执行所有数据库命令。
   [不使用该 connection 连接数据库执行的数据库命令,在本事务回滚的时候得不到回滚]
  (物理连接 connection 逻辑上新建一个会话session;
   DataSource 与 TransactionManager 配置相同的数据源)
 
2) 事务结束时,回滚在第1步骤中得到的代理 connection 对象上执行的数据库命令,
   然后关闭该代理 connection 对象。
  (事务结束后,回滚操作不会对已执行完毕的SQL操作命令起作用)

方案二(方案一改进版):update + @Transactional(update数据库表中时间段的status)

 该方法用update直接上独占锁(悲观锁),对比上一个方案,我们的范围缩小了

update完了之后可以返回数字1 or 0,如果1则表示更新成功,0则表示更新失败

0则返回controller,表示提交预约失败,以此来防止我们的并发问题

三、总结

1、得进行学习springboot得一些注解

2、学习进阶mysql锁的知识

3、有时候不进行正式的公司开发流程,真的不知道高级并发处理该咋搞

4、准备学习一下MybatisPlus

5、方案二的做法对比与方案一其实像乐观锁,大家可以细细品一下

6、update完status之后如果update成功的话就会submit我们的预约

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值