Springboot解决业务并发问题 您所在的位置:网站首页 springboot500错误总结 Springboot解决业务并发问题

Springboot解决业务并发问题

2024-01-15 01:58| 来源: 网络整理| 查看: 265

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

实现一种类似于医院预约的预约功能,在同一个时间段,可能大家都看得到这个预约的按钮,大家都点进去了,这个时候真正提交预约信息的时候,就会可能出现多个请求同一个时间段的预约,在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我们的预约



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有