「解决方案」SpringBoot项目中如何解决并发致使的重复提交问题

点击上方蓝色字体,选择“标星公众号”前端

优质文章,第一时间送达java

做者: 软件编程指南git

来源:http://suo.im/66liCE程序员

本文前篇是对场景的分析,后篇会有解决方案,读完本篇你将能够仅仅使用两个注解便可解决并发重复提交问题。github

能够直接看方案四,直接读推荐解决方案。web

场景分析

重复提交问题是一个老生常谈的问题,项目中常常会遇到这种状况,这种状况在查询类接口其实也没有太大问题,可是若是是在设计修改数据的接口就有会严重问题,可是这种状况并也不难处理,由于咱们的代码最少会作一个幂等判断,即会先有一个查询动做,查询不到才会放行。可是难就难在假如说是并发加剧复提交这种场景就很难处理。这个时候就不得不去思考新的解决方案。spring

解决方案
数据库

方案1、编程

经过数据库惟一索引来解决,即在数据库建立一张惟一表,在每次数据请求时候将惟一键做为数据插入这张惟一表中,正常状况是能够插入成功的,当出现重复提交状况就会异常提示。后端

缺点

  1. 数据库性能问题,由于每次操做都设计到数据库的一次插入动做,因此可能会有性能问题

  2. 数据只有一次处理机会,当第一次处理失败,第二次在进来就当重复给拦截了

方案2、

token令牌,后端提供一个生成令牌的接口,前端在每次进行数据访问时候,先拿去token令牌,后端经过对token令牌的生命周期管控,来解决重复提交问题

缺点: 先后端改造大,后端要单独维护一个接口,前端每次请求也要多调一个接口

总结

但愿经过查询+修改方式来解决并发和重复提交问题都是不现实的,由于不能保证查询和修改是一个原子性操做,因此只要并发就很容易突破这种方式的防重逻辑。那么如何解决这个问题呢? 其实就是保证防重逻辑的原子性操做。一样也是两种方案。

方案3、

相似于经过数据库惟一索引这种方式,不一样的是将数据库换成内存缓存即项目里定义一个Cache集合缓存能够用Guava的缓存框架,设置缓存时间和缓存数量来解决。不过也是有缺点的,缺点就是不知足分布式要求,当请求打到其余应用服务器就突破了这种状况。因此不建议使用这种方案。若是是单机器能够考虑。

方案4、

是对上一种方案的改进,经过Redis实现,每次请求都插入Redis数据库中,并设置过时时间, 既能知足性能需求,同时也知足分布式状况。同时Redis由于是单线程的因此也能保证原子性。综上所述这种方案应该是最好的。

  • 知足原子性

  • 知足分布式环境应用

  • 性能有保证

  • 支持重试(经过设置过时时间)


伪代码以下


终结解决方案

该方案是对上面方案四的一个实现,感兴趣的同窗一个start一下,而后拉下来看看实现原理。

核心原理就是方案四中提的,经过拦截和自动配置无缝整合到SpringBoot项目中使用。

官网地址: https://tomato.springlearn.cn/

使用方式

如何判断是否引用成功

当出现tomato Logo即说明启用成功

感兴趣的同窗能够学习一下代码,提出任何问题小编都会第一时间回复。一块儿探讨学习。

接下来小编会围绕Redis作更多的实战分享目前定下来的两个议题是:

1.基于Redis原子性操做实战应用一之并发拦截 「Tomato」

2.基于Redis原子性操做实战应用二之防洪限流「Easy-Sentinel」

这两个议题其实实战代码都已经写好了,只是尚未总结成文,感兴趣的同窗能够先到github上拉去实战代码。Tomato就是解决并发致使的重复提交,而Easy-Sentinel会更高级一点,利用Redis+Lua脚本实现原子性操做,从而来达到防洪限流的能力。


关注程序员闪充宝后台回复“666”和“111免费领取46阶段以及实战java视频资料



看完本文有收获?请转发分享给更多人

长按识别二维码关注


你在看?

本文分享自微信公众号 - 程序员闪充宝(cxyscb1024)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索