<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          分布式數(shù)據(jù)一致性思考-B端系統(tǒng)一致性

          共 2991字,需瀏覽 6分鐘

           ·

          2022-01-11 16:20

          往期熱門文章:

          1、Java字符串拼接的五種方法,哪種性能最好?
          2、一次線上JVM調(diào)優(yōu)實(shí)踐,F(xiàn)ullGC40次/天到10天一次的優(yōu)化過(guò)程
          3、Chrome 瀏覽器全球大翻車?讓 20 多億用戶無(wú)網(wǎng)可上
          4、while(1) 和 for(;;)有什么區(qū)別?
          5、使用MySQL,請(qǐng)用好 JSON 這張牌!

          轉(zhuǎn)自:cmlbeliever

          鏈接:?blog.csdn.net/cml_blog/article/details/107434967?spm=1001.2014.3001.5501

          背景

          最近在思考分布式一致性的理論與實(shí)現(xiàn)時(shí),感覺(jué)自己有所收獲,這里分享分享一下自己的經(jīng)驗(yàn)。


          什么是一致性?

          至于原理什么的,這里就不贅述了,總的來(lái)說(shuō)目前的分布式系統(tǒng)實(shí)現(xiàn)起來(lái)基本上都是基于BASE理論的,業(yè)務(wù)需要保持最終的一致性,說(shuō)白了了是可以允許 中間過(guò)程的短暫不一致,只需要最后一致就好。


          一說(shuō)到這個(gè),很多人馬上就能想到XA和TCC這兩種分布式事務(wù)的實(shí)現(xiàn),而且也有很多人針對(duì)這兩種思想設(shè)計(jì)出了很好的實(shí)現(xiàn),比如:tcc-lcn: https://github.com/codingapi/tx-lcn 還有很多的實(shí)現(xiàn),去github上一搜就能找到。


          但是基于XA需要有強(qiáng)大的事務(wù)管理器來(lái)協(xié)調(diào)事務(wù)操作,TCC的方式需要第三方協(xié)調(diào)者,多一個(gè)中間件就多一分維護(hù),同時(shí)業(yè)務(wù)難度也就上升很多 。當(dāng)然如果公司中有非常牛逼的中間件團(tuán)隊(duì)這個(gè)就基本可以忽略了,基本能保持最少4個(gè)9的可靠性。


          B端業(yè)務(wù)場(chǎng)景

          通常業(yè)務(wù)系統(tǒng)B端非常重視一致性,C端則更加重視高可用,在B端數(shù)據(jù)配置的時(shí)候通常都是需要調(diào)用好幾個(gè)系統(tǒng)才能完成一個(gè)數(shù)據(jù)的創(chuàng)建,如商品創(chuàng)建基本都需要


          1. 創(chuàng)建商品基礎(chǔ)數(shù)據(jù)

          2. 創(chuàng)建憑證模板

          3. 創(chuàng)建適用門店庫(kù)

          4. 創(chuàng)建xxx關(guān)聯(lián)數(shù)據(jù)

          5. 落本地?cái)?shù)據(jù)

          在這里的每一步都可能會(huì)失敗,比如網(wǎng)絡(luò)超時(shí),db抖動(dòng)等等常見(jiàn)的失敗原因。每一步失敗都意味著整個(gè)流程需要重試(更恐怖的是有的業(yè)務(wù)需要回滾前面的步驟)?;貪L基本不在業(yè)務(wù)考慮范圍內(nèi),因?yàn)楸緛?lái)業(yè)務(wù)就是要做好創(chuàng)建的工作,而且在校驗(yàn)階段都是符合創(chuàng)建條件的,那么業(yè)務(wù)上肯定是希望能夠完整的建好業(yè)務(wù)數(shù)據(jù),回滾只是作為非常規(guī)運(yùn)維手段來(lái)使用。


          可以需要通過(guò)以下幾個(gè)點(diǎn)來(lái)實(shí)現(xiàn)最終一致性.

          重試

          就像上面說(shuō)的,在這種可重試的失敗需要系統(tǒng)能夠自動(dòng)重試,重試的方法有很多,可以基于任何有定時(shí)任務(wù)功能的系統(tǒng)或框架來(lái)實(shí)行,如


          • linux的crontab

          • quartz

          • schedulerx

          • xxl-job

          等都符合重試的要求,處理業(yè)務(wù)的時(shí)候本地落一條流水?dāng)?shù)據(jù),失敗后設(shè)置可重試狀態(tài),等待定時(shí)任務(wù)來(lái)執(zhí)行。


          注意:


          • 重試的時(shí)候記錄好trace,這對(duì)排查問(wèn)題非常有幫助

          • 需要考慮好冪等性

          • 需要考慮好并發(fā)

          • 重試次數(shù)

          冪等

          在任務(wù)進(jìn)行重試執(zhí)行的時(shí)候,如何保證重復(fù)執(zhí)行的冪等性呢?首先:底層接口需要支持冪等,每次重試的時(shí)候業(yè)務(wù)流水id都保持一致,這樣通過(guò)流水id來(lái)實(shí)現(xiàn)冪等,防止數(shù)據(jù)重復(fù)創(chuàng)建。


          但是如果底層接口不支持冪等呢?(這種肯定有的,反正有各種歷史原因) 那么就需要業(yè)務(wù)自己來(lái)保證冪等了,在接口執(zhí)行的時(shí)候落一條流水記錄,執(zhí)行完成后更新流水,在執(zhí)行前先判斷流水是否已經(jīng)執(zhí)行成功,如果成功了就冪等返回,不做業(yè)務(wù)操作。


          通過(guò)本地落流水只能保證99%以上冪等,如果完全依賴這個(gè)做冪等那就想的太簡(jiǎn)單了,思考下,如果在調(diào)用某個(gè)接口的時(shí)候返回了超時(shí)的異常,此時(shí)流水狀態(tài)設(shè)置的還是失敗狀態(tài),等待重試的時(shí)候還是會(huì)進(jìn)行重復(fù)請(qǐng)求,這樣還是會(huì)重復(fù)創(chuàng)建數(shù)據(jù)。


          所以如果底層不支持流水冪等,而是支持業(yè)務(wù)冪等的話,如創(chuàng)建的時(shí)候有相同的id則會(huì)查詢一下本地DB,已經(jīng)有數(shù)據(jù)就返回指定的錯(cuò)誤碼,那么業(yè)務(wù)上還可以根據(jù)這個(gè)錯(cuò)誤碼進(jìn)行冪等處理。


          如果底層業(yè)務(wù)冪等都不支持,那這個(gè)就只能在處理的時(shí)候先查一次,再?zèng)Q定是否調(diào)用這個(gè)接口了(還是有風(fēng)險(xiǎn)的)。

          并發(fā)

          做好冪等其實(shí)還不夠,還需要做好并發(fā)處理,比如我的業(yè)務(wù)在處理的時(shí)候如果失敗了任務(wù)重復(fù)調(diào)度導(dǎo)致兩個(gè)任務(wù)一起執(zhí)行了,或者任務(wù)執(zhí)行的時(shí)候手動(dòng)觸發(fā)了任務(wù)執(zhí)行等,這些問(wèn)題都是存在的。


          要做好并發(fā)處理,優(yōu)先考慮使用分布式鎖,在業(yè)務(wù)處理前先獲取鎖,獲取鎖失敗則說(shuō)明已經(jīng)有任務(wù)在執(zhí)行了,當(dāng)前任務(wù)執(zhí)行結(jié)束,等待之前的任務(wù)執(zhí)行完成。


          加個(gè)分布式鎖就可以了?那也還是想的太簡(jiǎn)單了,考慮下這個(gè)場(chǎng)景


          第一次用戶編輯的時(shí)候,在執(zhí)行第三步的時(shí)候網(wǎng)絡(luò)超時(shí)失敗了,落了重試任務(wù),此時(shí)任務(wù)還沒(méi)開(kāi)始調(diào)度,用戶又開(kāi)始編輯數(shù)據(jù),此時(shí)執(zhí)行的時(shí)候獲取到了鎖,執(zhí)行成功了。然后定時(shí)任務(wù)調(diào)度拉起之前重試的任務(wù),繼續(xù)執(zhí)行第三步的操作,然后數(shù)據(jù)就被覆蓋了。。。


          這時(shí)聰明的你已經(jīng)想到了長(zhǎng)鎖+可重入鎖的方式了:

          業(yè)務(wù)執(zhí)行的時(shí)候先落一條長(zhǎng)鎖,只有執(zhí)行成功的時(shí)候才會(huì)釋放鎖,同時(shí)通過(guò)請(qǐng)求id作為可重入的判斷條件,業(yè)務(wù)失敗后任務(wù)拉起來(lái)執(zhí)行的時(shí)候還是相同的流水ID,這時(shí)任務(wù)是可以正常執(zhí)行的。此時(shí)用戶想要編輯數(shù)據(jù),則會(huì)獲取鎖失敗,用戶無(wú)法進(jìn)行編輯,此時(shí)給個(gè)友好的提示。

          這種方式還要注意一個(gè)點(diǎn),分布式鎖改為了分布式可重入鎖,那么并發(fā)問(wèn)題又來(lái)了,如果任務(wù)同時(shí)執(zhí)行了都是相同的流水id,都能正常執(zhí)行??梢酝ㄟ^(guò)如下的方式來(lái)避免這個(gè)


          • 通過(guò)限制可重入個(gè)數(shù)為1

          • 在業(yè)務(wù)內(nèi)部再加一個(gè)鎖

          小結(jié)

          考慮好冪等,并發(fā),重試這幾個(gè)問(wèn)題后,整個(gè)業(yè)務(wù)系統(tǒng)就可以非常健壯的跑起來(lái)了。

          那么問(wèn)題來(lái)了,為什么只要重試而不需要做回滾呢?


          會(huì)進(jìn)入任務(wù)執(zhí)行的時(shí)候,需要基礎(chǔ)校驗(yàn)都已經(jīng)完成了,校驗(yàn)通過(guò)后說(shuō)明數(shù)據(jù)是允許執(zhí)行的,既然已經(jīng)拿到了執(zhí)行的門票,那么我們的任務(wù)就是要保證創(chuàng)建成功,至于回滾等操作只會(huì)在底層數(shù)據(jù)出現(xiàn)問(wèn)題,無(wú)法執(zhí)行完整的創(chuàng)建流程,需要回滾之前的操作。


          實(shí)際業(yè)務(wù)上使用的時(shí)候基本不會(huì)去寫回滾的邏輯的,首先加重了開(kāi)發(fā)的任務(wù),其次回滾這種邏輯更適合作為運(yùn)維手段來(lái)執(zhí)行,這里可以考慮下原因哦。

          會(huì)進(jìn)入任務(wù)執(zhí)行的時(shí)候,需要基礎(chǔ)校驗(yàn)都已經(jīng)完成了,校驗(yàn)通過(guò)后說(shuō)明數(shù)據(jù)是允許執(zhí)行的,既然已經(jīng)拿到了執(zhí)行的門票,那么我們的任務(wù)就是要保證創(chuàng)建成功,至于回滾等操作只會(huì)在底層數(shù)據(jù)出現(xiàn)問(wèn)題,無(wú)法執(zhí)行完整的創(chuàng)建流程,需要回滾之前的操作。實(shí)際業(yè)務(wù)上使用的時(shí)候基本不會(huì)去寫回滾的邏輯的,首先加重了開(kāi)發(fā)的任務(wù),其次回滾這種邏輯更適合作為運(yùn)維手段來(lái)執(zhí)行,這里可以考慮下原因哦。

          總結(jié)

          總結(jié)下來(lái)的流程圖如下,歡迎給出寶貴的意見(jiàn)和建議?。?!

          目前接觸下來(lái)的開(kāi)發(fā)團(tuán)隊(duì),幾乎沒(méi)人使用分布式事務(wù)來(lái)保證數(shù)據(jù)的一致性,那么問(wèn)題來(lái)了,

          1 你在用么?

          2 自建還是直接用開(kāi)源的?

          最近熱文閱讀:

          1、Java字符串拼接的五種方法,哪種性能最好?
          2、一次線上JVM調(diào)優(yōu)實(shí)踐,F(xiàn)ullGC40次/天到10天一次的優(yōu)化過(guò)程
          3、Chrome 瀏覽器全球大翻車?讓 20 多億用戶無(wú)網(wǎng)可上
          4、while(1) 和 for(;;)有什么區(qū)別?
          5、使用MySQL,請(qǐng)用好 JSON 這張牌!
          6、延時(shí)任務(wù)實(shí)現(xiàn)方案
          7、服務(wù)端如何防止重復(fù)支付
          8、五年工作經(jīng)驗(yàn)總結(jié) 16 條的代碼規(guī)范
          9、為什么我勸你放棄了Restful API?
          10、Java8 Stream:2萬(wàn)字20個(gè)實(shí)例,玩轉(zhuǎn)集合的篩選、歸約、分組、聚合
          關(guān)注公眾號(hào),你想要的Java都在這里

          瀏覽 25
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲成人高清 | 久久九九国产视频 | 狠狠人妻久久久久久综合 | 国产黄色视频哪里看 | 九九精品久久久久久久久无码人妻 |