成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

分布式鎖和spring事務(wù)管理

shinezejian / 2544人閱讀

摘要:否則數(shù)據(jù)會出現(xiàn)不同步問題我使用的做分布式鎖管理,用注解事務(wù)管理。但是出現(xiàn)另外一個問題,鎖超時但是事務(wù)仍未提交。

最近開發(fā)一個小程序遇到一個需求需要實現(xiàn)分布式事務(wù)管理

業(yè)務(wù)需求

用戶在使用小程序的過程中可以查看景點,對景點地區(qū)或者城市標(biāo)記是否想去,那么需要統(tǒng)計一個地點被標(biāo)記的人數(shù),以及記錄某個用戶對某個地點是否標(biāo)記為想去,用兩個表存儲數(shù)據(jù),一個地點表記錄改地點被標(biāo)記的次數(shù),一個用戶意向表記錄某個用戶對某個地點是否標(biāo)記為想去。由于可能有多個用戶同時標(biāo)記一個地點,每個用戶在前端點擊想去按鈕之后,后臺接收到請求,從數(shù)據(jù)庫查詢某個城市的標(biāo)記人數(shù),再加1,然后更新到數(shù)據(jù)庫。從數(shù)據(jù)庫查詢標(biāo)記人數(shù),再加1,然后更新到數(shù)據(jù)庫這個過程數(shù)據(jù)庫數(shù)據(jù)必須加鎖,一次只能一個進程處理。否則數(shù)據(jù)會出現(xiàn)不同步問題

我使用的RedLock做分布式鎖管理,用spring注解事務(wù)管理。
在實現(xiàn)過程中遇到如下兩個映像深刻的問題:
1、分布式鎖與spring注解事務(wù)共用產(chǎn)生的問題
2、鎖在事務(wù)提交前超時問題

使用分布式鎖RedLock及spring事務(wù)實現(xiàn)

最初實現(xiàn)代碼如下:

 public markScenicSpot(){
  //設(shè)置鎖為destId
   RLock lock = redisson.getLock("Afanti_markScenicSpot_updateCountwantAndCountbeenLock_" + ID);
   //嘗試獲取鎖
   long lockTimeOut = 30; //持有鎖超時時間
   **boolean success = lock.tryLock(5, lockTimeOut, TimeUnit.SECONDS);**
   if (success) {
      try {
          //業(yè)務(wù)邏輯實現(xiàn)
      }catch (Exception e){
          throw e;
      } finally{
          //釋放鎖
          **lock.unlock();**
      }
   } else {
       log.error("獲取鎖失??!更新失敗!");
       throw new BizException(ErrorCodeEnum.PROCESS_DATA_ERROR);
   }
 }

問題:高并發(fā)是鎖沒有生效

1、spring注解事務(wù)@Transactional和分布式鎖不能一起使用
這是因為@Transactional是通過方法是否拋出異常來判斷事務(wù)是否回滾還是提交,此時方法已經(jīng)結(jié)束。但是我們必須在方法結(jié)束之前釋放鎖,
因此在釋放鎖之后,此時還沒提交,由于鎖已經(jīng)釋放,其他進程可以獲得鎖,并從數(shù)據(jù)庫查詢地點標(biāo)記數(shù),但是此時前一個進程沒有提交數(shù)據(jù)。該進程查到的數(shù)據(jù)不是最新的數(shù)據(jù)。
這個問題我排查的時候花了很久,因為鎖釋放和提交事務(wù)之間只要幾毫秒的時間,之前一直以為這么短的時間不可能是這里的問題,有懷疑過但是自己又放棄了
盡管這個過程只要很短的時間(我實際測試過程中這個過程只要幾毫秒),但是高并發(fā)的情況還是會出問題。

解決1:

由于不能使用注解事務(wù),我改為手動事務(wù)管理,增加如下代碼。

 public markScenicSpot(){
   //設(shè)置鎖為destId
   RLock lock = redisson.getLock("Afanti_markScenicSpot_updateCountwantAndCountbeenLock_" + ID);
   //嘗試獲取鎖
   long lockTimeOut = 30; //持有鎖超時時間
   boolean success = lock.tryLock(5, lockTimeOut, TimeUnit.SECONDS);
   if(success){
      **DefaultTransactionDefinition def = new DefaultTransactionDefinition();
      def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // 事物隔離級別
      TransactionStatus status = transactionManager.getTransaction(def); // 獲得事務(wù)狀態(tài)**
      try {
          //業(yè)務(wù)邏輯實現(xiàn)
          //......
          **//提交事務(wù)
          transactionManager.commit(status);**
      }catch (Exception e){
          **//回滾事務(wù)
          transactionManager.rollback(status);**
      } finally{
          //釋放鎖
          lock.unlock();
      }
   } else {
       log.error("獲取鎖失??!更新失??!");
       throw new BizException(ErrorCodeEnum.PROCESS_DATA_ERROR);
   }
 }

問題:鎖超時事物異常

1、鎖超時問題
在進行手動事務(wù)管理之后,解決的同步問題。但是出現(xiàn)另外一個問題,鎖超時但是事務(wù)仍未提交。由于此時當(dāng)前進程鎖超時但是沒有提交,此時其他進程可以獲得鎖并從數(shù)據(jù)庫查詢目的地標(biāo)記數(shù),但是不是更新之后的數(shù)據(jù),取得的數(shù)據(jù)有誤。

解決2:

針對鎖超時的情況,只需要當(dāng)前進程提交之前增加一個判斷,判斷是否超時,如果超時拋出異常退出即可。
增加如下代碼:

public markScenicSpot(){
   //設(shè)置鎖為destId
   RLock lock = redisson.getLock("Afanti_markScenicSpot_updateCountwantAndCountbeenLock_" + ID);
   //嘗試獲取鎖
   long lockTimeOut = 30; //持有鎖超時時間
   boolean success = lock.tryLock(5, lockTimeOut, TimeUnit.SECONDS);
   **//獲取鎖時間
   long getLockTime=System.currentTimeMillis();**
   if(success){
      //事務(wù)管理
      DefaultTransactionDefinition def = new DefaultTransactionDefinition();
      def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // 事物隔離級別
      TransactionStatus status = transactionManager.getTransaction(def); // 獲得事務(wù)狀態(tài)
      try {
          //業(yè)務(wù)邏輯實現(xiàn)
          //......
          //提交事務(wù),判斷鎖是否超時
          **if(System.currentTimeMillis()-getLockTime
總結(jié)

高并發(fā)情況下,分布式事務(wù)很容易出問題,要對各種情況分析是否可能出問題,并要對所有可能出問題的情況做充分的測試才能保證程序健壯。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/76878.html

相關(guān)文章

  • 架構(gòu)~微服務(wù) - 收藏集 - 掘金

    摘要:它就是史上最簡單的教程第三篇服務(wù)消費者后端掘金上一篇文章,講述了通過去消費服務(wù),這篇文章主要講述通過去消費服務(wù)。概覽和架構(gòu)設(shè)計掘金技術(shù)征文后端掘金是基于的一整套實現(xiàn)微服務(wù)的框架。 Spring Boot 配置文件 – 在坑中實踐 - 后端 - 掘金作者:泥瓦匠鏈接:Spring Boot 配置文件 – 在坑中實踐版權(quán)歸作者所有,轉(zhuǎn)載請注明出處本文提綱一、自動配置二、自定義屬性三、ran...

    church 評論0 收藏0
  • Spring Boot+SQL/JPA實戰(zhàn)悲觀鎖和樂觀鎖

    摘要:所以悲觀鎖是限制其他線程,而樂觀鎖是限制自己,雖然他的名字有鎖,但是實際上不算上鎖,只是在最后操作的時候再判斷具體怎么操作。悲觀鎖和樂觀鎖比較悲觀鎖適合寫多讀少的場景。 最近在公司的業(yè)務(wù)上遇到了并發(fā)的問題,并且還是很常見的并發(fā)問題,算是低級的失誤了。由于公司業(yè)務(wù)相對比較復(fù)雜且不適合公開,在此用一個很常見的業(yè)務(wù)來還原一下場景,同時介紹悲觀鎖和樂觀鎖是如何解決這類并發(fā)問題的。 公司業(yè)務(wù)就是...

    Keven 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<