最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JPA使用樂觀鎖應(yīng)對高并發(fā)方式

 更新時間:2021年10月15日 10:22:02   作者:yunterry  
這篇文章主要介紹了JPA使用樂觀鎖應(yīng)對高并發(fā)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

JPA使用樂觀鎖應(yīng)對高并發(fā)

高并發(fā)系統(tǒng)的挑戰(zhàn)

在部署分布式系統(tǒng)時,我們通常把多個微服務(wù)部署在內(nèi)網(wǎng)集群中,再用API網(wǎng)關(guān)聚合起來對外提供。為了做負載均衡,通常會對每個微服務(wù)都啟動多個運行實例,通過注冊中心去調(diào)用。

那么問題來了,因為有多個實例運行都是同一個應(yīng)用,雖然微服務(wù)網(wǎng)關(guān)會把每一個請求只轉(zhuǎn)發(fā)給一個實例,但當(dāng)面對高并發(fā)時,但它們?nèi)匀豢赡芡瑫r操作同一個數(shù)據(jù)庫表,這會不會引發(fā)什么問題呢?

悲觀鎖的問題

比如電商中常見的商品秒殺系統(tǒng),在用戶搶購商品過程中,會有大量并發(fā)請求,很可能同時讀寫一個包含商品剩余數(shù)量的表,這種一般要給數(shù)據(jù)庫加鎖,否則很容易出現(xiàn)商品超賣錯賣的情況。

如果使用數(shù)據(jù)庫自帶的鎖機制,也就是悲觀鎖,在寫入的時候鎖定數(shù)據(jù)庫,其他修改請求到來時就必須等待鎖釋放,但這就使效率降下來了,而且高并發(fā)場景下可能有的請求一直搶不到鎖,就會長時間卡在那導(dǎo)致請求失敗,然后有大量重試,系統(tǒng)可能會發(fā)生連接數(shù)耗盡等異常。

樂觀鎖是個好東西

查閱資料發(fā)現(xiàn)樂觀鎖是個好東西,它是為數(shù)據(jù)庫表增加一個標(biāo)識數(shù)據(jù)版本的version字段來實現(xiàn)的,讀取數(shù)據(jù)時把version字段一同讀出,寫入數(shù)據(jù)庫時比對version字段就知道數(shù)據(jù)是否被更改過,如果version不相等就說明持有的是過期數(shù)據(jù),不能寫入,如果相等就可以寫入,并把version加一。

樂觀鎖在寫入數(shù)據(jù)庫的時候,才會檢查數(shù)據(jù)是否沖突,如果發(fā)現(xiàn)沖突了,就放棄寫入,返回寫入失敗的信息,相比于悲觀鎖,這是一種輕量級的對數(shù)據(jù)的鎖定方式,能夠應(yīng)對高并發(fā)需求。

給數(shù)據(jù)庫添加樂觀鎖

說樂觀鎖是個好東西,首先得說 JPA 是個好東西,因為Spring Data JPA已經(jīng)內(nèi)置了樂觀鎖的實現(xiàn),給數(shù)據(jù)庫表添加樂觀鎖很簡單,添加一個整型字段,并加入@Version注解就可以了,每次提交數(shù)據(jù)時JPA會自動檢查版本。

    @Entity  
    @Table(name = "m_order")  
    public class Order {  
    ...  
        @Version  
        private int version;  
    ...  
    }  

樂觀鎖 -業(yè)務(wù)判斷 解決高并發(fā)

在解決高并發(fā)問題時,如果是分布式系統(tǒng)顯然我們只能夠使用數(shù)據(jù)庫端加鎖機制來解決這個問題,但是這種同步機制或者數(shù)據(jù)庫物理鎖機制會犧牲一部分的性能,所以常常以另外一種方式來解決這個問題 就是樂觀鎖模式

銀行兩操作員同時操作同一賬戶就是典型的樂觀鎖模式。

比如A、B操作員同時讀取一余額為1000元的賬戶,A操作員為該賬戶增加100元,B操作員同時為該賬戶扣除50元,A先提交,B后提交。最后實際賬戶余額為1000-50=950元,但本該為1000+100-50=1050。這就是典型的并發(fā)問題。

樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基于數(shù)據(jù)版本(Version)記錄機制實現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個版本標(biāo)識,在基于數(shù)據(jù)庫表的版本解決方案中,一般是通過為數(shù)據(jù)庫表增加一個 “version” 字段來實現(xiàn)。

讀取出數(shù)據(jù)時,將此版本號一同讀出,之后更新時,對此版本號加一。此時,將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息進行比對,如果提交的數(shù)據(jù)版本號大于數(shù)據(jù)庫表當(dāng)前版本號,則予以更新,否則認為是過期數(shù)據(jù)。

對于上面修改用戶帳戶信息的例子而言,假設(shè)數(shù)據(jù)庫中帳戶信息表中有一個version字段,當(dāng)前值為1;而當(dāng)前帳戶余額字段(balance)為1000元。假設(shè)操作員A先更新完,操作員B后更新。

  • a、操作員A此時將其讀出(version=1),并從其帳戶余額中增加100(1000+100=1100)。
  • b、在操作員A操作的過程中,操作員B也讀入此用戶信息(version=1),并從其帳戶余額中扣除50(1000-50=950)。
  • c、操作員A完成了修改工作,將數(shù)據(jù)版本號加一(version=2),連同帳戶增加后余額(balance=1100),提交至數(shù)據(jù)庫更新,此時由于提交數(shù)據(jù)版本大于數(shù)據(jù)庫記錄當(dāng)前版本,數(shù)據(jù)被更新,數(shù)據(jù)庫記錄version更新為2。
  • d、操作員B完成了操作,也將版本號加一(version=2)試圖向數(shù)據(jù)庫提交數(shù)據(jù)(balance=950),但此時比對數(shù)據(jù)庫記錄版本時發(fā)現(xiàn),操作員B提交的數(shù)據(jù)版本號為2,數(shù)據(jù)庫記錄當(dāng)前版本也為2,不滿足 “提交版本必須大于記錄當(dāng)前版本才能執(zhí)行更新 “的樂觀鎖策略,因此,操作員B的提交被駁回。
  • 這樣,就避免了操作員B用基于version=1的舊數(shù)據(jù)修改的結(jié)果覆蓋操作員A的操作結(jié)果的可能。

操作員A操作如下:

select id, balance, version from account where id="1"; 
查詢結(jié)果:id=1, balance=1000, version=1
update account 
set balance=balance+100, version=version+1 
where id="1" and version=1
select id, balance, version from account where id="1"; 
查詢結(jié)果:id=1, balance=1100, version=2

操作員B操作如下:

select id, balance, version from account where id="1"; 
查詢結(jié)果:id=1, balance=1000, version=1
#操作員A已修改成功,實際account.balance=1100、account.version=2,操作員B也將版本號加一(version=2)試圖向數(shù)據(jù)庫提交數(shù)據(jù)(balance=950),但此時比對數(shù)據(jù)庫記錄版本時發(fā)現(xiàn),操作員B提交的數(shù)據(jù)版本號為2,數(shù)據(jù)庫記錄當(dāng)前版本也為2,不滿足 “提交版本必須大于記錄當(dāng)前版本才能執(zhí)行更新 “的樂觀鎖策略,因此,操作員B的提交被駁回。
update account 
set balance=balance-50, version=version+1 
where id="1" and version=1 
select id, balance, version from account where id="1"; 
查詢結(jié)果:id=1, balance=1100, version=2

Hibernate、JPA等ORM框架或者實現(xiàn),是使用版本號,再判斷UPDATE后返回的數(shù)值

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 在Java中使用MongoDB的方法詳解

    在Java中使用MongoDB的方法詳解

    這篇文章主要給大家介紹了關(guān)于在Java中使用MongoDB的相關(guān)資料,要操作MongoDB數(shù)據(jù)庫你需要使用MongoDB的Java驅(qū)動程序,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-12-12
  • Idea連接GitLab的過程以及創(chuàng)建在gitlab中創(chuàng)建用戶和群組方式

    Idea連接GitLab的過程以及創(chuàng)建在gitlab中創(chuàng)建用戶和群組方式

    本文介紹了如何在IDEA中連接GitLab,首先需安裝GitLab插件并配置SSH免密登錄,接著,創(chuàng)建GitLab個人令牌并在Git中配置,文章還提到了如何在GitLab中創(chuàng)建用戶、群組及設(shè)置權(quán)限,如Owner、Maintainer、Developer等,并強調(diào)了群組名和人員名稱的命名規(guī)范
    2024-11-11
  • SpringBoot如何監(jiān)聽redis?Key變化事件案例詳解

    SpringBoot如何監(jiān)聽redis?Key變化事件案例詳解

    項目中需要監(jiān)聽redis的一些事件比如鍵刪除,修改,過期等,下面這篇文章主要給大家介紹了關(guān)于SpringBoot如何監(jiān)聽redis?Key變化事件的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-08-08
  • 基于MapperXML掃描的問題

    基于MapperXML掃描的問題

    這篇文章主要介紹了MapperXML掃描的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java如何從不規(guī)則的字符串中截取出日期

    java如何從不規(guī)則的字符串中截取出日期

    這篇文章主要介紹了java從不規(guī)則的字符串中截取出日期的方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java中的AWT事件處理問題

    java中的AWT事件處理問題

    這篇文章主要介紹了java中的AWT事件處理問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 關(guān)于各種排列組合java算法實現(xiàn)方法

    關(guān)于各種排列組合java算法實現(xiàn)方法

    這篇文章介紹了幾種用JAVA實現(xiàn)的排列組合算法,有需要的朋友可以參考一下
    2013-06-06
  • Java中常見的5種WEB服務(wù)器介紹

    Java中常見的5種WEB服務(wù)器介紹

    這篇文章主要介紹了Java中常見的5種WEB服務(wù)器介紹,它們分別是Tomcat、Resin、JBoss、WebSphere、WebLogic,需要的朋友可以參考下
    2014-07-07
  • Spring的InitializingBean接口解析

    Spring的InitializingBean接口解析

    這篇文章主要介紹了Spring的InitializingBean接口解析,InitializingBean是spring為bean的初始化提供了一種新的方式,里面只有一個方法afterPropertiesSet,作用就是實現(xiàn)這個接口或者實現(xiàn)了繼承InitializingBean的方法的bean都要執(zhí)行這個方法,需要的朋友可以參考下
    2024-02-02
  • 詳解SpringBoot定時任務(wù)說明

    詳解SpringBoot定時任務(wù)說明

    本篇文章主要介紹了詳解SpringBoot定時任務(wù)說明,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03

最新評論

屏东市| 都安| 邵阳市| 东乌珠穆沁旗| 吉安市| 德兴市| 罗田县| 临桂县| 扶绥县| 江华| 淮安市| 来安县| 临澧县| 桐城市| 凌源市| 兰溪市| 任丘市| 中宁县| 宣汉县| 开平市| 崇仁县| 康保县| 泾川县| 澄城县| 樟树市| 沙田区| 库尔勒市| 香港| 通州区| 稻城县| 淮滨县| 南通市| 云南省| 醴陵市| 松阳县| 普定县| 鹿泉市| 璧山县| 东丰县| 礼泉县| 牙克石市|