「解決方案」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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索