<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>

          面渣逆襲:分布式十二問(wèn)!萬(wàn)字圖文詳解!

          共 12323字,需瀏覽 25分鐘

           ·

          2023-02-25 02:08

          大家好,我是老三,不管今年金三銀四如何,面渣逆襲系列繼續(xù),這期我們來(lái)看看分布式。

          分布式理論

          1. 說(shuō)說(shuō)CAP原則?

          CAP原則又稱CAP定理,指的是在一個(gè)分布式系統(tǒng)中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區(qū)容錯(cuò)性)這3個(gè)基本需求,最多只能同時(shí)滿足其中的2個(gè)。

          CAP原則
          選項(xiàng)描述
          Consistency(一致性)指數(shù)據(jù)在多個(gè)副本之間能夠保持一致的特性(嚴(yán)格的一致性)
          Availability(可用性)指系統(tǒng)提供的服務(wù)必須一直處于可用的狀態(tài),每次請(qǐng)求都能獲取到非錯(cuò)的響應(yīng)(不保證獲取的數(shù)據(jù)為最新數(shù)據(jù))
          Partition tolerance(分區(qū)容錯(cuò)性)分布式系統(tǒng)在遇到任何網(wǎng)絡(luò)分區(qū)故障的時(shí)候,仍然能夠?qū)ν馓峁M足一致性和可用性的服務(wù),除非整個(gè)網(wǎng)絡(luò)環(huán)境都發(fā)生了故障

          2. 為什么CAP不可兼得呢?

          首先對(duì)于分布式系統(tǒng),分區(qū)是必然存在的,所謂分區(qū)指的是分布式系統(tǒng)可能出現(xiàn)的字區(qū)域網(wǎng)絡(luò)不通,成為孤立區(qū)域的的情況。

          分區(qū)

          那么分區(qū)容錯(cuò)性(P)就必須要滿足,因?yàn)槿绻獱奚謪^(qū)容錯(cuò)性,就得把服務(wù)和資源放到一個(gè)機(jī)器,或者一個(gè)“同生共死”的集群,那就違背了分布式的初衷。

          那么滿足分區(qū)容錯(cuò)的基礎(chǔ)上,能不能同時(shí)滿足一致性可用性

          假如現(xiàn)在有兩個(gè)分區(qū)N1N2,N1和N2分別有不同的分區(qū)存儲(chǔ)D1和D2,以及不同的服務(wù)S1和S2。

          • 在滿足一致性 的時(shí)候,N1和N2的數(shù)據(jù)要求值一樣的,D1=D2。
          • 在滿足可用性的時(shí)候,無(wú)論訪問(wèn)N1還是N2,都能獲取及時(shí)的響應(yīng)。
          分區(qū)的服務(wù)

          假如現(xiàn)在有這樣的場(chǎng)景:

          • 用戶訪問(wèn)了N1,修改了D1的數(shù)據(jù)。
          • 用戶再次訪問(wèn),請(qǐng)求落在了N2。此時(shí)D1和D2的數(shù)據(jù)不一致。

          接下來(lái):

          • 保證一致性:此時(shí)D1和D2數(shù)據(jù)不一致,要保證一致性就不能返回不一致的數(shù)據(jù),可用性無(wú)法保證。
          • 保證可用性:立即響應(yīng),可用性得到了保證,但是此時(shí)響應(yīng)的數(shù)據(jù)和D1不一致,一致性無(wú)法保證。

          所以,可以看出,分區(qū)容錯(cuò)的前提下,一致性可用性是矛盾的。

          3. CAP對(duì)應(yīng)的模型和應(yīng)用?

          CA without P

          理論上放棄P(分區(qū)容錯(cuò)性),則C(強(qiáng)一致性)和A(可用性)是可以保證的。實(shí)際上分區(qū)是不可避免的,嚴(yán)格上CA指的是允許分區(qū)后各子系統(tǒng)依然保持CA。

          CA模型的常見(jiàn)應(yīng)用:

          • 集群數(shù)據(jù)庫(kù)
          • xFS文件系統(tǒng)

          CP without A

          放棄A(可用),相當(dāng)于每個(gè)請(qǐng)求都需要在Server之間強(qiáng)一致,而P(分區(qū))會(huì)導(dǎo)致同步時(shí)間無(wú)限延長(zhǎng),如此CP也是可以保證的。很多傳統(tǒng)的數(shù)據(jù)庫(kù)分布式事務(wù)都屬于這種模式。

          CP模型的常見(jiàn)應(yīng)用:

          • 分布式數(shù)據(jù)庫(kù)
          • 分布式鎖

          AP wihtout C

          要高可用并允許分區(qū),則需放棄一致性。一旦分區(qū)發(fā)生,節(jié)點(diǎn)之間可能會(huì)失去聯(lián)系,為了高可用,每個(gè)節(jié)點(diǎn)只能用本地?cái)?shù)據(jù)提供服務(wù),而這樣會(huì)導(dǎo)致全局?jǐn)?shù)據(jù)的不一致性?,F(xiàn)在眾多的NoSQL都屬于此類。

          AP模型常見(jiàn)應(yīng)用:

          • Web緩存
          • DNS

          舉個(gè)大家更熟悉的例子,像我們熟悉的注冊(cè)中心ZooKeeper、Eureka、Nacos中:

          • ZooKeeper 保證的是 CP
          • Eureka 保證的則是 AP
          • Nacos 不僅支持 CP 也支持 AP

          4. BASE理論了解嗎?

          BASE(Basically Available、Soft state、Eventual consistency)是基于CAP理論逐步演化而來(lái)的,核心思想是即便不能達(dá)到強(qiáng)一致性(Strong consistency),也可以根據(jù)應(yīng)用特點(diǎn)采用適當(dāng)?shù)姆绞絹?lái)達(dá)到最終一致性(Eventual consistency)的效果。

          BASE的主要含義:

          • Basically Available(基本可用)

          什么是基本可用呢?假設(shè)系統(tǒng)出現(xiàn)了不可預(yù)知的故障,但還是能用,只是相比較正常的系統(tǒng)而言,可能會(huì)有響應(yīng)時(shí)間上的損失,或者功能上的降級(jí)。

          • Soft State(軟狀態(tài))

          什么是硬狀態(tài)呢?要求多個(gè)節(jié)點(diǎn)的數(shù)據(jù)副本都是一致的,這是一種“硬狀態(tài)”。

          軟狀態(tài)也稱為弱狀態(tài),相比較硬狀態(tài)而言,允許系統(tǒng)中的數(shù)據(jù)存在中間狀態(tài),并認(rèn)為該狀態(tài)不影響系統(tǒng)的整體可用性,即允許系統(tǒng)在多個(gè)不同節(jié)點(diǎn)的數(shù)據(jù)副本存在數(shù)據(jù)延時(shí)。

          • Eventually Consistent(最終一致性)

          上面說(shuō)了軟狀態(tài),但是不應(yīng)該一直都是軟狀態(tài)。在一定時(shí)間后,應(yīng)該到達(dá)一個(gè)最終的狀態(tài),保證所有副本保持?jǐn)?shù)據(jù)一致性,從而達(dá)到數(shù)據(jù)的最終一致性。這個(gè)時(shí)間取決于網(wǎng)絡(luò)延時(shí)、系統(tǒng)負(fù)載、數(shù)據(jù)復(fù)制方案設(shè)計(jì)等等因素。

          分布式鎖

          單體時(shí)代,可以直接用本地鎖來(lái)實(shí)現(xiàn)對(duì)競(jìng)爭(zhēng)資源的加鎖,分布式環(huán)境下就要用到分布式鎖了。

          5. 有哪些分布式鎖的實(shí)現(xiàn)方案呢?

          常見(jiàn)的分布式鎖實(shí)現(xiàn)方案有三種:MySQL分布式鎖ZooKepper分布式鎖Redis分布式鎖。

          分布式鎖

          5.1 MySQL分布式鎖如何實(shí)現(xiàn)呢?

          用數(shù)據(jù)庫(kù)實(shí)現(xiàn)分布式鎖比較簡(jiǎn)單,就是創(chuàng)建一張鎖表,數(shù)據(jù)庫(kù)對(duì)字段作唯一性約束。

          加鎖的時(shí)候,在鎖表中增加一條記錄即可;釋放鎖的時(shí)候刪除記錄就行。

          如果有并發(fā)請(qǐng)求同時(shí)提交到數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)會(huì)保證只有一個(gè)請(qǐng)求能夠得到鎖。

          這種屬于數(shù)據(jù)庫(kù) IO 操作,效率不高,而且頻繁操作會(huì)增大數(shù)據(jù)庫(kù)的開(kāi)銷,因此這種方式在高并發(fā)、高性能的場(chǎng)景中用的不多。

          5.2 ZooKeeper如何實(shí)現(xiàn)分布式鎖?

          ZooKeeper也是常見(jiàn)分布式鎖實(shí)現(xiàn)方法。

          ZooKeeper的數(shù)據(jù)節(jié)點(diǎn)和文件目錄類似,例如有一個(gè)lock節(jié)點(diǎn),在此節(jié)點(diǎn)下建立子節(jié)點(diǎn)是可以保證先后順序的,即便是兩個(gè)進(jìn)程同時(shí)申請(qǐng)新建節(jié)點(diǎn),也會(huì)按照先后順序建立兩個(gè)節(jié)點(diǎn)。

          ZooKeeper如何實(shí)現(xiàn)分布式鎖

          所以我們可以用此特性實(shí)現(xiàn)分布式鎖。以某個(gè)資源為目錄,然后這個(gè)目錄下面的節(jié)點(diǎn)就是我們需要獲取鎖的客戶端,每個(gè)服務(wù)在目錄下創(chuàng)建節(jié)點(diǎn),如果它的節(jié)點(diǎn),序號(hào)在目錄下最小,那么就獲取到鎖,否則等待。釋放鎖,就是刪除服務(wù)創(chuàng)建的節(jié)點(diǎn)。

          ZK實(shí)際上是一個(gè)比較重的分布式組件,實(shí)際上應(yīng)用沒(méi)那么多了,所以用ZK實(shí)現(xiàn)分布式鎖,其實(shí)相對(duì)也比較少。

          5.3 Redis怎么實(shí)現(xiàn)分布式鎖?

          Redis實(shí)現(xiàn)分布式鎖,是當(dāng)前應(yīng)用最廣泛的分布式鎖實(shí)現(xiàn)方式。

          Redis執(zhí)行命令是單線程的,Redis實(shí)現(xiàn)分布式鎖就是利用這個(gè)特性。

          實(shí)現(xiàn)分布式鎖最簡(jiǎn)單的一個(gè)命令:setNx(set if not exist),如果不存在則更新:

          setNx resourceName value

          加鎖了之后如果機(jī)器宕機(jī),那我這個(gè)鎖就無(wú)法釋放,所以需要加入過(guò)期時(shí)間,而且過(guò)期時(shí)間需要和setNx同一個(gè)原子操作,在Redis2.8之前需要用lua腳本,但是redis2.8之后redis支持nx和ex操作是同一原子操作。

          set resourceName value ex 5 nx
          • Redission

          當(dāng)然,一般生產(chǎn)中都是使用Redission客戶端,非常良好地封裝了分布式鎖的api,而且支持RedLock。

          分布式事務(wù)

          6.什么是分布式事務(wù)?

          分布式事務(wù)是相對(duì)本地事務(wù)而言的,對(duì)于本地事務(wù),利用數(shù)據(jù)庫(kù)本身的事務(wù)機(jī)制,就可以保證事務(wù)的ACID特性。

          ACID

          而在分布式環(huán)境下,會(huì)涉及到多個(gè)數(shù)據(jù)庫(kù)。

          多數(shù)據(jù)庫(kù)

          分布式事務(wù)其實(shí)就是將對(duì)同一庫(kù)事務(wù)的概念擴(kuò)大到了對(duì)多個(gè)庫(kù)的事務(wù)。目的是為了保證分布式系統(tǒng)中的數(shù)據(jù)一致性。

          分布式事務(wù)處理的關(guān)鍵是:

          1. 需要記錄事務(wù)在任何節(jié)點(diǎn)所做的所有動(dòng)作;
          2. 事務(wù)進(jìn)行的所有操作要么全部提交,要么全部回滾。

          7.分布式事務(wù)有哪些常見(jiàn)的實(shí)現(xiàn)方案?

          分布式常見(jiàn)的實(shí)現(xiàn)方案有 2PC3PC、TCC、本地消息表、MQ消息事務(wù)、最大努力通知、SAGA事務(wù) 等等。

          7.1 說(shuō)說(shuō)2PC兩階段提交?

          說(shuō)到2PC,就不得先說(shuō)分布式事務(wù)中的 XA 協(xié)議。

          在這個(gè)協(xié)議里,有三個(gè)角色:

          • AP(Application):應(yīng)用系統(tǒng)(服務(wù))
          • TM(Transaction Manager):事務(wù)管理器(全局事務(wù)管理)
          • RM(Resource Manager):資源管理器(數(shù)據(jù)庫(kù))
          XA協(xié)議

          XA協(xié)議采用兩階段提交方式來(lái)管理分布式事務(wù)。XA接口提供資源管理器與事務(wù)管理器之間進(jìn)行通信的標(biāo)準(zhǔn)接口。

          兩階段提交的思路可以概括為:參與者將操作成敗通知協(xié)調(diào)者,再由協(xié)調(diào)者根據(jù)所有參與者的反饋情況決定各參與者是否要提交操作還是回滾操作。

          2PC
          • 準(zhǔn)備階段:事務(wù)管理器要求每個(gè)涉及到事務(wù)的數(shù)據(jù)庫(kù)預(yù)提交(precommit)此操作,并反映是否可以提交
          • 提交階段:事務(wù)協(xié)調(diào)器要求每個(gè)數(shù)據(jù)庫(kù)提交數(shù)據(jù),或者回滾數(shù)據(jù)。

          優(yōu)點(diǎn):盡量保證了數(shù)據(jù)的強(qiáng)一致,實(shí)現(xiàn)成本較低,在各大主流數(shù)據(jù)庫(kù)都有自己實(shí)現(xiàn),對(duì)于MySQL是從5.5開(kāi)始支持。

          缺點(diǎn):

          • 單點(diǎn)問(wèn)題:事務(wù)管理器在整個(gè)流程中扮演的角色很關(guān)鍵,如果其宕機(jī),比如在第一階段已經(jīng)完成,在第二階段正準(zhǔn)備提交的時(shí)候事務(wù)管理器宕機(jī),資源管理器就會(huì)一直阻塞,導(dǎo)致數(shù)據(jù)庫(kù)無(wú)法使用。
          • 同步阻塞:在準(zhǔn)備就緒之后,資源管理器中的資源一直處于阻塞,直到提交完成,釋放資源。
          • 數(shù)據(jù)不一致:兩階段提交協(xié)議雖然為分布式數(shù)據(jù)強(qiáng)一致性所設(shè)計(jì),但仍然存在數(shù)據(jù)不一致性的可能,比如在第二階段中,假設(shè)協(xié)調(diào)者發(fā)出了事務(wù)commit的通知,但是因?yàn)榫W(wǎng)絡(luò)問(wèn)題該通知僅被一部分參與者所收到并執(zhí)行了commit操作,其余的參與者則因?yàn)闆](méi)有收到通知一直處于阻塞狀態(tài),這時(shí)候就產(chǎn)生了數(shù)據(jù)的不一致性。

          7.2 3PC(三階段提交)了解嗎?

          三階段提交(3PC)是二階段提交(2PC)的一種改進(jìn)版本 ,為解決兩階段提交協(xié)議的單點(diǎn)故障和同步阻塞問(wèn)題。

          三階段提交有這么三個(gè)階段:CanCommit,PreCommitDoCommit三個(gè)階段

          3PC
          • CanCommit:準(zhǔn)備階段。協(xié)調(diào)者向參與者發(fā)送commit請(qǐng)求,參與者如果可以提交就返回Yes響應(yīng),否則返回No響應(yīng)。
          • PreCommit:預(yù)提交階段。協(xié)調(diào)者根據(jù)參與者在準(zhǔn)備階段的響應(yīng)判斷是否執(zhí)行事務(wù)還是中斷事務(wù),參與者執(zhí)行完操作之后返回ACK響應(yīng),同時(shí)開(kāi)始等待最終指令。
          • DoCommit:提交階段。協(xié)調(diào)者根據(jù)參與者在準(zhǔn)備階段的響應(yīng)判斷是否執(zhí)行事務(wù)還是中斷事務(wù):
            • 如果所有參與者都返回正確的ACK響應(yīng),則提交事務(wù)
            • 如果參與者有一個(gè)或多個(gè)參與者收到錯(cuò)誤的ACK響應(yīng)或者超時(shí),則中斷事務(wù)
            • 如果參與者無(wú)法及時(shí)接收到來(lái)自協(xié)調(diào)者的提交或者中斷事務(wù)請(qǐng)求時(shí),在等待超時(shí)之后,會(huì)繼續(xù)進(jìn)行事務(wù)提交

          可以看出,三階段提交解決的只是兩階段提交中單體故障同步阻塞的問(wèn)題,因?yàn)榧尤肓顺瑫r(shí)機(jī)制,這里的超時(shí)的機(jī)制作用于 預(yù)提交階段提交階段。如果等待 預(yù)提交請(qǐng)求 超時(shí),參與者直接回到準(zhǔn)備階段之前。如果等到提交請(qǐng)求超時(shí),那參與者就會(huì)提交事務(wù)了。

          無(wú)論是2PC還是3PC都不能保證分布式系統(tǒng)中的數(shù)據(jù)100%一致。

          7.3 TCC了解嗎?

          TCC(Try Confirm Cancel) ,是兩階段提交的一個(gè)變種,針對(duì)每個(gè)操作,都需要有一個(gè)其對(duì)應(yīng)的確認(rèn)和取消操作,當(dāng)操作成功時(shí)調(diào)用確認(rèn)操作,當(dāng)操作失敗時(shí)調(diào)用取消操作,類似于二階段提交,只不過(guò)是這里的提交和回滾是針對(duì)業(yè)務(wù)上的,所以基于TCC實(shí)現(xiàn)的分布式事務(wù)也可以看做是對(duì)業(yè)務(wù)的一種補(bǔ)償機(jī)制。

          TCC下單減庫(kù)存
          • Try:嘗試待執(zhí)行的業(yè)務(wù)。訂單系統(tǒng)將當(dāng)前訂單狀態(tài)設(shè)置為支付中,庫(kù)存系統(tǒng)校驗(yàn)當(dāng)前剩余庫(kù)存數(shù)量是否大于1,然后將可用庫(kù)存數(shù)量設(shè)置為庫(kù)存剩余數(shù)量-1,。

          • Confirm:確認(rèn)執(zhí)行業(yè)務(wù),如果Try階段執(zhí)行成功,接著執(zhí)行Confirm 階段,將訂單狀態(tài)修改為支付成功,庫(kù)存剩余數(shù)量修改為可用庫(kù)存數(shù)量。

          • Cancel:取消待執(zhí)行的業(yè)務(wù),如果Try階段執(zhí)行失敗,執(zhí)行Cancel 階段,將訂單狀態(tài)修改為支付失敗,可用庫(kù)存數(shù)量修改為庫(kù)存剩余數(shù)量。

          TCC 是業(yè)務(wù)層面的分布式事務(wù),保證最終一致性,不會(huì)一直持有資源的鎖。

          • 優(yōu)點(diǎn): 把數(shù)據(jù)庫(kù)層的二階段提交交給應(yīng)用層來(lái)實(shí)現(xiàn),規(guī)避了數(shù)據(jù)庫(kù)的 2PC 性能低下問(wèn)題
          • 缺點(diǎn):TCC 的 Try、Confirm 和 Cancel 操作功能需業(yè)務(wù)提供,開(kāi)發(fā)成本高。TCC 對(duì)業(yè)務(wù)的侵入較大和業(yè)務(wù)緊耦合,需要根據(jù)特定的場(chǎng)景和業(yè)務(wù)邏輯來(lái)設(shè)計(jì)相應(yīng)的操作

          7.4 本地消息表了解嗎?

          本地消息表的核心思想是將分布式事務(wù)拆分成本地事務(wù)進(jìn)行處理。

          例如,可以在訂單庫(kù)新增一個(gè)消息表,將新增訂單和新增消息放到一個(gè)事務(wù)里完成,然后通過(guò)輪詢的方式去查詢消息表,將消息推送到MQ,庫(kù)存服務(wù)去消費(fèi)MQ。

          本地消息表

          執(zhí)行流程:

          1. 訂單服務(wù),添加一條訂單和一條消息,在一個(gè)事務(wù)里提交
          2. 訂單服務(wù),使用定時(shí)任務(wù)輪詢查詢狀態(tài)為未同步的消息表,發(fā)送到MQ,如果發(fā)送失敗,就重試發(fā)送
          3. 庫(kù)存服務(wù),接收MQ消息,修改庫(kù)存表,需要保證冪等操作
          4. 如果修改成功,調(diào)用rpc接口修改訂單系統(tǒng)消息表的狀態(tài)為已完成或者直接刪除這條消息
          5. 如果修改失敗,可以不做處理,等待重試

          訂單服務(wù)中的消息有可能由于業(yè)務(wù)問(wèn)題會(huì)一直重復(fù)發(fā)送,所以為了避免這種情況可以記錄一下發(fā)送次數(shù),當(dāng)達(dá)到次數(shù)限制之后報(bào)警,人工接入處理;庫(kù)存服務(wù)需要保證冪等,避免同一條消息被多次消費(fèi)造成數(shù)據(jù)不一致。

          本地消息表這種方案實(shí)現(xiàn)了最終一致性,需要在業(yè)務(wù)系統(tǒng)里增加消息表,業(yè)務(wù)邏輯中多一次插入的DB操作,所以性能會(huì)有損耗,而且最終一致性的間隔主要有定時(shí)任務(wù)的間隔時(shí)間決定

          7.5 MQ消息事務(wù)了解嗎?

          消息事務(wù)的原理是將兩個(gè)事務(wù)通過(guò)消息中間件進(jìn)行異步解耦。

          訂單服務(wù)執(zhí)行自己的本地事務(wù),并發(fā)送MQ消息,庫(kù)存服務(wù)接收消息,執(zhí)行自己的本地事務(wù),乍一看,好像跟本地消息表的實(shí)現(xiàn)方案類似,只是省去 了對(duì)本地消息表的操作和輪詢發(fā)送MQ的操作,但實(shí)際上兩種方案的實(shí)現(xiàn)是不一樣的。

          消息事務(wù)一定要保證業(yè)務(wù)操作與消息發(fā)送的一致性,如果業(yè)務(wù)操作成功,這條消息也一定投遞成功。

          MQ消息事務(wù)

          執(zhí)行流程:

          1. 發(fā)送prepare消息到消息中間件
          2. 發(fā)送成功后,執(zhí)行本地事務(wù)
          3. 如果事務(wù)執(zhí)行成功,則commit,消息中間件將消息下發(fā)至消費(fèi)端
          4. 如果事務(wù)執(zhí)行失敗,則回滾,消息中間件將這條prepare消息刪除
          5. 消費(fèi)端接收到消息進(jìn)行消費(fèi),如果消費(fèi)失敗,則不斷重試

          消息事務(wù)依賴于消息中間件的事務(wù)消息,例如我們熟悉的RocketMQ就支持事務(wù)消息(半消息),也就是只有收到發(fā)送方確定才會(huì)正常投遞的消息。

          這種方案也是實(shí)現(xiàn)了最終一致性,對(duì)比本地消息表實(shí)現(xiàn)方案,不需要再建消息表,對(duì)性能的損耗和業(yè)務(wù)的入侵更小。

          7.6 最大努力通知了解嗎?

          最大努力通知相比實(shí)現(xiàn)會(huì)簡(jiǎn)單一些,適用于一些對(duì)最終一致性實(shí)時(shí)性要求沒(méi)那么高的業(yè)務(wù),比如支付通知,短信通知。

          以支付通知為例,業(yè)務(wù)系統(tǒng)調(diào)用支付平臺(tái)進(jìn)行支付,支付平臺(tái)進(jìn)行支付,進(jìn)行操作支付之后支付平臺(tái)會(huì)去同步通知業(yè)務(wù)系統(tǒng)支付操作是否成功,如果不成功,會(huì)一直異步重試,但是會(huì)有一個(gè)最大通知次數(shù),如果超過(guò)這個(gè)次數(shù)后還是通知失敗,就不再通知,業(yè)務(wù)系統(tǒng)自行調(diào)用支付平臺(tái)提供一個(gè)查詢接口,供業(yè)務(wù)系統(tǒng)進(jìn)行查詢支付操作是否成功。

          最大努力通知

          執(zhí)行流程:

          1. 業(yè)務(wù)系統(tǒng)調(diào)用支付平臺(tái)支付接口, 并在本地進(jìn)行記錄,支付狀態(tài)為支付中
          2. 支付平臺(tái)進(jìn)行支付操作之后,無(wú)論成功還是失敗,同步給業(yè)務(wù)系統(tǒng)一個(gè)結(jié)果通知
          3. 如果通知一直失敗則根據(jù)重試規(guī)則異步進(jìn)行重試,達(dá)到最大通知次數(shù)后,不再通知
          4. 支付平臺(tái)提供查詢訂單支付操作結(jié)果接口
          5. 業(yè)務(wù)系統(tǒng)根據(jù)一定業(yè)務(wù)規(guī)則去支付平臺(tái)查詢支付結(jié)果

          8.你們用什么?能說(shuō)一下Seata嗎?

          我們用比較常用的是Seata——自己去實(shí)現(xiàn)分布式事務(wù)調(diào)度還是比較麻煩的。

          Seata 的設(shè)計(jì)目標(biāo)是對(duì)業(yè)務(wù)無(wú)侵入,因此它是從業(yè)務(wù)無(wú)侵入的兩階段提交(全局事務(wù))著手,在傳統(tǒng)的兩階段上進(jìn)行改進(jìn),他把一個(gè)分布式事務(wù)理解成一個(gè)包含了若干分支事務(wù)的全局事務(wù)。而全局事務(wù)的職責(zé)是協(xié)調(diào)它管理的分支事務(wù)達(dá)成一致性,要么一起成功提交,要么一起失敗回滾。也就是一榮俱榮一損俱損~

          全局事務(wù)和分支事務(wù)

          Seata 中存在這么幾種重要角色:

          • TC(Transaction Coordinator):事務(wù)協(xié)調(diào)者。管理全局的分支事務(wù)的狀態(tài),用于全局性事務(wù)的提交和回滾。
          • TM(Transaction Manager):事務(wù)管理者。用于開(kāi)啟、提交或回滾事務(wù)。
          • RM(Resource Manager):資源管理器。用于分支事務(wù)上的資源管理,向 TC 注冊(cè)分支事務(wù),上報(bào)分支事務(wù)的狀態(tài),接收 TC 的命令來(lái)提交或者回滾分支事務(wù)。
          Seata工作流程

          S'eata整體執(zhí)行流程:

          1. 服務(wù)A中的 TMTC 申請(qǐng)開(kāi)啟一個(gè)全局事務(wù),TC 就會(huì)創(chuàng)建一個(gè)全局事務(wù)并返回一個(gè)唯一的 XID
          2. 服務(wù)A中的 RMTC 注冊(cè)分支事務(wù),然后將這個(gè)分支事務(wù)納入 XID 對(duì)應(yīng)的全局事務(wù)管轄中
          3. 服務(wù)A開(kāi)始執(zhí)行分支事務(wù)
          4. 服務(wù)A開(kāi)始遠(yuǎn)程調(diào)用B服務(wù),此時(shí) XID 會(huì)根據(jù)調(diào)用鏈傳播
          5. 服務(wù)B中的 RM 也向 TC 注冊(cè)分支事務(wù),然后將這個(gè)分支事務(wù)納入 XID 對(duì)應(yīng)的全局事務(wù)管轄中
          6. 服務(wù)B開(kāi)始執(zhí)行分支事務(wù)
          7. 全局事務(wù)調(diào)用處理結(jié)束后,TM 會(huì)根據(jù)有誤異常情況,向 TC 發(fā)起全局事務(wù)的提交或回滾
          8. TC 協(xié)調(diào)其管轄之下的所有分支事務(wù),決定是提交還是回滾

          分布式一致性算法

          9.分布式算法paxos了解么 ?

          Paxos 有點(diǎn)類似前面說(shuō)的 2PC,3PC,但比這兩種算法更加完善。在很多多大廠都得到了工程實(shí)踐,比如阿里的 OceanBase分布式數(shù)據(jù)庫(kù)Googlechubby 分布式鎖 。

          Paxos算法是什么?

          Paxos 算法是 基于消息傳遞 且具有 高效容錯(cuò)特性 的一致性算法,目前公認(rèn)的解決 分布式一致性問(wèn)題 最有效的算法之一。

          Paxos算法的工作流程?

          角色

          在Paxos中有這么幾個(gè)角色:

          1. Proposer(提議者) : 提議者提出提案,用于投票表決。
          2. Accecptor(接受者) : 對(duì)提案進(jìn)行投票,并接受達(dá)成共識(shí)的提案。
          3. Learner(學(xué)習(xí)者) : 被告知投票的結(jié)果,接受達(dá)成共識(shí)的提案。

          在實(shí)際中,一個(gè)節(jié)點(diǎn)可以同時(shí)充當(dāng)不同角色。

          Paxos的三種角色

          提議者提出提案,提案=編號(hào)+value,可以表示為[M,V],每個(gè)提案都有唯一編號(hào),而且編號(hào)的大小是趨勢(shì)遞增的。

          算法流程

          Paxos算法包含兩個(gè)階段,第一階段**Prepare(準(zhǔn)備)、第二階段Accept(接受)**。

          Paxos算法流程
          Prepare(準(zhǔn)備)階段
          1. 提議者提議一個(gè)新的提案 P[Mn,?],然后向接受者的某個(gè)超過(guò)半數(shù)的子集成員發(fā)送編號(hào)為Mn的準(zhǔn)備請(qǐng)求
          2. 如果一個(gè)接受者收到一個(gè)編號(hào)為Mn的準(zhǔn)備請(qǐng)求,并且編號(hào)Mn大于它已經(jīng)響應(yīng)的所有準(zhǔn)備請(qǐng)求的編號(hào),那么它就會(huì)將它已經(jīng)批準(zhǔn)過(guò)的最大編號(hào)的提案作為響應(yīng)反饋給提議者,同時(shí)該接受者會(huì)承諾不會(huì)再批準(zhǔn)任何編號(hào)小于Mn的提案。

          總結(jié)一下,接受者在收到提案后,會(huì)給與提議者兩個(gè)承諾一個(gè)應(yīng)答

          • 兩個(gè)承諾:
            • 承諾不會(huì)再接受提案號(hào)小于或等于 Mn 的 Prepare 請(qǐng)求
            • 承諾不會(huì)再接受提案號(hào)小于Mn 的 Accept 請(qǐng)求
          • 一個(gè)應(yīng)答:
            • 不違背以前作出的承諾的前提下,回復(fù)已經(jīng)通過(guò)的提案中提案號(hào)最大的那個(gè)提案所設(shè)定的值和提案號(hào)Mmax,如果這個(gè)值從來(lái)沒(méi)有被任何提案設(shè)定過(guò),則返回空值。如果不滿足已經(jīng)做出的承諾,即收到的提案號(hào)并不是決策節(jié)點(diǎn)收到過(guò)的最大的,那允許直接對(duì)此 Prepare 請(qǐng)求不予理會(huì)。
          Accept(接受)階段
          1. 如果提議者收到來(lái)自半數(shù)以上的接受者對(duì)于它發(fā)出的編號(hào)為Mn的準(zhǔn)備請(qǐng)求的響應(yīng),那么它就會(huì)發(fā)送一個(gè)針對(duì)[Mn,Vn]的接受請(qǐng)求給接受者,注意Vn的值就是收到的響應(yīng)中編號(hào)最大的提案的值,如果響應(yīng)中不包含任何提案,那么它可以隨意選定一個(gè)值。
          2. 如果接受者收到這個(gè)針對(duì)[Mn,Vn]提案的接受請(qǐng)求,只要該接受者尚未對(duì)編號(hào)大于Mn的準(zhǔn)備請(qǐng)求做出響應(yīng),它就可以通過(guò)這個(gè)提案。

          當(dāng)提議者收到了多數(shù)接受者的接受應(yīng)答后,協(xié)商結(jié)束,共識(shí)決議形成,將形成的決議發(fā)送給所有學(xué)習(xí)節(jié)點(diǎn)進(jìn)行學(xué)習(xí)。

          所以Paxos算法的整體詳細(xì)流程如下:

          Paxos詳細(xì)流程

          算法的流程模擬,可以查看參考[13]。

          Paxos算法有什么缺點(diǎn)嗎?怎么優(yōu)化?

          前面描述的可以稱之為Basic Paxos 算法,在單提議者的前提下是沒(méi)有問(wèn)題的,但是假如有多個(gè)提議者互不相讓,那么就可能導(dǎo)致整個(gè)提議的過(guò)程進(jìn)入了死循環(huán)。

          Lamport 提出了 Multi Paxos 的算法思想。

          Multi Paxos算法思想,簡(jiǎn)單說(shuō)就是在多個(gè)提議者的情況下,選出一個(gè)Leader(領(lǐng)導(dǎo)者),由領(lǐng)導(dǎo)者作為唯一的提議者,這樣就可以解決提議者沖突的問(wèn)題。

          10.說(shuō)說(shuō)Raft算法?

          Raft算法是什么?

          Raft 也是一個(gè) 一致性算法,和 Paxos 目標(biāo)相同。但它還有另一個(gè)名字 - 易于理解的一致性算法PaxosRaft 都是為了實(shí)現(xiàn) 一致性 產(chǎn)生的。這個(gè)過(guò)程如同選舉一樣,參選者 需要說(shuō)服 大多數(shù)選民 (Server) 投票給他,一旦選定后就跟隨其操作。PaxosRaft 的區(qū)別在于選舉的 具體過(guò)程 不同。

          Raft算法的工作流程?

          Raft算法的角色

          Raft 協(xié)議將 Server 進(jìn)程分為三種角色:

          • Leader(領(lǐng)導(dǎo)者)
          • Follower(跟隨者)
          • Candidate(候選人)

          就像一個(gè)民主社會(huì),領(lǐng)導(dǎo)者由跟隨者投票選出。剛開(kāi)始沒(méi)有 領(lǐng)導(dǎo)者,所有集群中的 參與者 都是 跟隨者。

          那么首先開(kāi)啟一輪大選。在大選期間 所有跟隨者 都能參與競(jìng)選,這時(shí)所有跟隨者的角色就變成了 候選人,民主投票選出領(lǐng)袖后就開(kāi)始了這屆領(lǐng)袖的任期,然后選舉結(jié)束,所有除 領(lǐng)導(dǎo)者候選人 又變回 跟隨者 服從領(lǐng)導(dǎo)者領(lǐng)導(dǎo)。

          這里提到一個(gè)概念 「任期」,用術(shù)語(yǔ) Term 表達(dá)。

          三類角色的變遷圖如下:

          Raft三種角色變遷圖

          Leader選舉過(guò)程

          Raft 使用心跳(heartbeat)觸發(fā)Leader選舉。當(dāng)Server啟動(dòng)時(shí),初始化為Follower。Leader向所有Followers周期性發(fā)送heartbeat。如果Follower在選舉超時(shí)時(shí)間內(nèi)沒(méi)有收到Leader的heartbeat,就會(huì)等待一段隨機(jī)的時(shí)間后發(fā)起一次Leader選舉。

          Follower將其當(dāng)前term加一然后轉(zhuǎn)換為Candidate。它首先給自己投票并且給集群中的其他服務(wù)器發(fā)送 RequestVote RPC 。結(jié)果有以下三種情況:

          • 贏得了多數(shù)(超過(guò)1/2)的選票,成功選舉為L(zhǎng)eader;
          • 收到了Leader的消息,表示有其它服務(wù)器已經(jīng)搶先當(dāng)選了Leader;
          • 沒(méi)有Server贏得多數(shù)的選票,Leader選舉失敗,等待選舉時(shí)間超時(shí)(Election Timeout)后發(fā)起下一次選舉。
          Leader選舉

          選出 Leader 后,Leader 通過(guò) 定期 向所有 Follower 發(fā)送 心跳信息 維持其統(tǒng)治。若 Follower 一段時(shí)間未收到 Leader心跳,則認(rèn)為 Leader 可能已經(jīng)掛了,然后再次發(fā)起 選舉 過(guò)程。

          分布式設(shè)計(jì)

          11.說(shuō)說(shuō)什么是冪等性?

          什么是冪等性?

          冪等性是一個(gè)數(shù)學(xué)概念,用在接口上:用在接口上就可以理解為:同一個(gè)接口,多次發(fā)出同一個(gè)請(qǐng)求,請(qǐng)求的結(jié)果是一致的。

          簡(jiǎn)單說(shuō),就是多次調(diào)用如一次。

          什么是冪等性問(wèn)題?

          在系統(tǒng)的運(yùn)行中,可能會(huì)出現(xiàn)這樣的問(wèn)題:

          1. 用戶在填寫(xiě)某些form表單時(shí),保存按鈕不小心快速點(diǎn)了兩次,表中竟然產(chǎn)生了兩條重復(fù)的數(shù)據(jù),只是id不一樣。
          2. 開(kāi)發(fā)人員在項(xiàng)目中為了解決接口超時(shí)問(wèn)題,通常會(huì)引入了重試機(jī)制。第一次請(qǐng)求接口超時(shí)了,請(qǐng)求方?jīng)]能及時(shí)獲取返回結(jié)果(此時(shí)有可能已經(jīng)成功了),于是會(huì)對(duì)該請(qǐng)求重試幾次,這樣也會(huì)產(chǎn)生重復(fù)的數(shù)據(jù)。
          3. mq消費(fèi)者在讀取消息時(shí),有時(shí)候會(huì)讀取到重復(fù)消息,也會(huì)產(chǎn)生重復(fù)的數(shù)據(jù)。

          這些都是常見(jiàn)的冪等性問(wèn)題。

          在分布式系統(tǒng)里,只要下游服務(wù)有寫(xiě)(保存、更新)的操作,都有可能會(huì)產(chǎn)生冪等性問(wèn)題。

          PS:冪等和防重有些不同,防重強(qiáng)調(diào)的防止數(shù)據(jù)重復(fù),冪等強(qiáng)調(diào)的是多次調(diào)用如一次,防重包含冪等。

          怎么保證接口冪等性?

          接口冪等性
          1. insert前先select

            在保存數(shù)據(jù)的接口中,在insert前,先根據(jù)requestId等字段先select一下數(shù)據(jù)。如果該數(shù)據(jù)已存在,則直接返回,如果不存在,才執(zhí)行  insert操作。

          2. 加唯一索引

            加唯一索引是個(gè)非常簡(jiǎn)單但很有效的辦法,如果重復(fù)插入數(shù)據(jù)的話,就會(huì)拋出異常,為了保證冪等性,一般需要捕獲這個(gè)異常。

            如果是java程序需要捕獲:DuplicateKeyException異常,如果使用了spring框架還需要捕獲:MySQLIntegrityConstraintViolationException異常。

          3. 加悲觀鎖

            更新邏輯,比如更新用戶賬戶余額,可以加悲觀鎖,把對(duì)應(yīng)用戶的哪一行數(shù)據(jù)鎖住。同一時(shí)刻只允許一個(gè)請(qǐng)求獲得鎖,其他請(qǐng)求則等待。

            select * from user id=123 for update;

            這種方式有一個(gè)缺點(diǎn),獲取不到鎖的請(qǐng)求一般只能報(bào)失敗,比較難保證接口返回相同值。

          4. 加樂(lè)觀鎖

            更新邏輯,也可以用樂(lè)觀鎖,性能更好??梢栽诒碇性黾右粋€(gè)timestamp或者version字段,例如version:

            在更新前,先查詢一下數(shù)據(jù),將version也作為更新的條件,同時(shí)也更新version:

            update user set amount=amount+100,version=version+1 where id=123 and version=1;

            更新成功后,version增加,重復(fù)更新請(qǐng)求進(jìn)來(lái)就無(wú)法更新了。

          5. 建防重表

            有時(shí)候表中并非所有的場(chǎng)景都不允許產(chǎn)生重復(fù)的數(shù)據(jù),只有某些特定場(chǎng)景才不允許。這時(shí)候,就可以使用防重表的方式。

            例如消息消費(fèi)中,創(chuàng)建防重表,存儲(chǔ)消息的唯一ID,消費(fèi)時(shí)先去查詢是否已經(jīng)消費(fèi),已經(jīng)消費(fèi)直接返回成功。

          6. 狀態(tài)機(jī)

            有些業(yè)務(wù)表是有狀態(tài)的,比如訂單表中有:1-下單、2-已支付、3-完成、4-撤銷等狀態(tài),可以通過(guò)限制狀態(tài)的流動(dòng)來(lái)完成冪等。

          7. 分布式鎖

            直接在數(shù)據(jù)庫(kù)上加鎖的做法性能不夠友好,可以使用分布式鎖的方式,目前最流行的分布式鎖實(shí)現(xiàn)是通過(guò)Redis,具體實(shí)現(xiàn)一般都是使用Redission框架。

          8. token機(jī)制

            請(qǐng)求接口之前,需要先獲取一個(gè)唯一的token,再帶著這個(gè)token去完成業(yè)務(wù)操作,服務(wù)端根據(jù)這個(gè)token是否存在,來(lái)判斷是否是重復(fù)的請(qǐng)求。

          分布式限流

          12.你了解哪些限流算法?

          • 計(jì)數(shù)器

          計(jì)數(shù)器比較簡(jiǎn)單粗暴,比如我們要限制1s能夠通過(guò)的請(qǐng)求數(shù),實(shí)現(xiàn)的思路就是從第一個(gè)請(qǐng)求進(jìn)來(lái)開(kāi)始計(jì)時(shí),在接下來(lái)的1s內(nèi),每個(gè)請(qǐng)求進(jìn)來(lái)請(qǐng)求數(shù)就+1,超過(guò)最大請(qǐng)求數(shù)的請(qǐng)求會(huì)被拒絕,等到1s結(jié)束后計(jì)數(shù)清零,重新開(kāi)始計(jì)數(shù)。

          這種方式有個(gè)很大的弊端:比如前10ms已經(jīng)通過(guò)了最大的請(qǐng)求數(shù),那么后面的990ms的請(qǐng)求只能拒絕,這種現(xiàn)象叫做“突刺現(xiàn)象”。

          • 漏桶算法

          就是桶底出水的速度恒定,進(jìn)水的速度可能快慢不一,但是當(dāng)進(jìn)水量大于出水量的時(shí)候,水會(huì)被裝在桶里,不會(huì)直接被丟棄;但是桶也是有容量限制的,當(dāng)桶裝滿水后溢出的部分還是會(huì)被丟棄的。

          算法實(shí)現(xiàn):可以準(zhǔn)備一個(gè)隊(duì)列來(lái)保存暫時(shí)處理不了的請(qǐng)求,然后通過(guò)一個(gè)線程池定期從隊(duì)列中獲取請(qǐng)求來(lái)執(zhí)行。

          漏桶算法
          • 令牌桶算法

          令牌桶就是生產(chǎn)訪問(wèn)令牌的一個(gè)地方,生產(chǎn)的速度恒定,用戶訪問(wèn)的時(shí)候當(dāng)桶中有令牌時(shí)就可以訪問(wèn),否則將觸發(fā)限流。

          實(shí)現(xiàn)方案:Guava RateLimiter限流

          Guava RateLimiter是一個(gè)谷歌提供的限流,其基于令牌桶算法,比較適用于單實(shí)例的系統(tǒng)。

          令牌桶算法

          這一期的分布式面試題就整理到這里了,主要是偏理論的一些問(wèn)題,分布式其實(shí)是個(gè)很大的類型,比如分布式調(diào)用、分布式治理……

          所以,這篇文章只是個(gè)開(kāi)始,后面還會(huì)有分布式調(diào)用(RPC)、微服務(wù)相關(guān)的主題文章,敬請(qǐng)期待。



          參考:

          [1] . 《從Paxos到Zookeeper 分布式一致性原理與實(shí)踐》
          [2]. 分布式理論(一) - CAP定理:https://juejin.cn/post/6844903621490901006
          [3]. 分布式理論(二) - BASE理論 :https://juejin.cn/post/6844903621495095304
          [4]. 分布式理論(三) - 2PC協(xié)議:https://juejin.cn/post/6844903621495095309
          [5] . CAP和BASE理論了解么?可以結(jié)合實(shí)際案例說(shuō)下不:https://juejin.cn/post/6898288789371027470
          [6] 從分布式事務(wù)解決到Seata使用,一梭子給你整明白了:https://juejin.cn/post/6944882663148748807
          [7]. 高并發(fā)下如何保證接口的冪等性?:https://juejin.cn/post/6944559294939398158)
          [8]. 分布式理論(三) - 2PC協(xié)議 :https://juejin.cn/post/6844903621495095309
          [9]. 再有人問(wèn)你分布式鎖,這篇文章扔給他:https://juejin.cn/post/6844903688088059912)
          [10]. 分布式理論(五) - 一致性算法Paxos :https://juejin.cn/post/6844903621499289613)
          [11]. 《分布式系統(tǒng)技術(shù)及其案例分析》
          [12].不就是分布式事務(wù),這下徹底清楚了??:https://juejin.cn/post/7008939082579443748)
          [13].諸葛亮 VS 龐統(tǒng),拿下 Paxos 共識(shí)算法:http://www.passjava.cn/#/03.Distributed/05.諸葛VS龐統(tǒng),拿下Paxos?id=諸葛亮-vs-龐統(tǒng),拿下-paxos-共識(shí)算法
          [14].http://icyfenix.cn/distribution/consensus/paxos.html


          ??面渣逆襲系列:


          面渣逆襲系列已經(jīng)結(jié)集成冊(cè),持續(xù)更新維護(hù)中,關(guān)注公眾號(hào)「三分惡」,回復(fù)「666」即可無(wú)套路獲??!

          面渣逆襲手冊(cè)

          瀏覽 28
          點(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>
                  欧美乱伦中文字幕 | 亚洲精品国产精品乱码桃花 | 勉费黄片 | 99超碰在线公开 | 不卡影院亚洲 |