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

          為什么單體不用考慮一致性而分布式需要?

          共 7101字,需瀏覽 15分鐘

           ·

          2024-04-12 05:07


          ??目錄


          1 背景

              1.1 數(shù)據(jù)存儲(chǔ)讀取

          2 數(shù)據(jù)存儲(chǔ)一致性

              2.1 主從架構(gòu)

              2.2 主主架構(gòu)

              2.3 無(wú)主架構(gòu)

          3 總結(jié)




          軟件開發(fā)領(lǐng)域有一個(gè)著名的“不可能三角”——質(zhì)量、成本、時(shí)間,三者無(wú)法兼得。這也是 IT 行業(yè)沒(méi)有銀彈解決方案的根因所在,就好像分布式系統(tǒng)在帶來(lái)高并發(fā)能力,突破 CPU 計(jì)算瓶頸與存儲(chǔ)限制時(shí),不可避免地帶來(lái)了數(shù)據(jù)一致性的問(wèn)題。

          網(wǎng)上談?wù)摂?shù)據(jù)一致性的文章不少,大多從算法的角度切入,本文作者選擇了從服務(wù)架構(gòu)的角度切入,詳細(xì)拆解了主從架構(gòu)、主主架構(gòu)、無(wú)主架構(gòu)三種架構(gòu)模式下,數(shù)據(jù)一致性的難點(diǎn)與解決方案。





          01



          背景


          隨著軟件規(guī)模的不斷擴(kuò)大,服務(wù)也不得不從單體應(yīng)用走向分布式部署,通過(guò)分布式應(yīng)用的部署使我們極大程度地提高了系統(tǒng)的并發(fā)量,突破了 CPU 計(jì)算的瓶頸,也突破了磁盤存儲(chǔ)的限制,看似我們使用了分布式技術(shù)就能夠解決所有問(wèn)題。但是任何技術(shù)都不是銀彈。


          解決問(wèn)題的同時(shí)也帶來(lái)相應(yīng)的“副作用”——數(shù)據(jù)一致性問(wèn)題。在分布式場(chǎng)景下,數(shù)據(jù)的處理存儲(chǔ)讀取由原先的單節(jié)點(diǎn)拓展成為了多節(jié)點(diǎn),由于服務(wù)對(duì)外表現(xiàn)需要一致,意味著需要多節(jié)點(diǎn)協(xié)同數(shù)據(jù)保持一致,但是達(dá)到數(shù)據(jù)一致并不是一件簡(jiǎn)單的事情,后面其實(shí)需要做很多的努力。



          下面我們來(lái)看下分布式場(chǎng)景下是如何影響數(shù)據(jù)一致性的。


             1.1 數(shù)據(jù)存儲(chǔ)讀取


          數(shù)據(jù)庫(kù)是我們?nèi)粘P枰蚪坏赖淖畛R姷闹虚g件,承載著數(shù)據(jù)存儲(chǔ)的任務(wù)。但是在分布式場(chǎng)景下,這確實(shí)會(huì)帶來(lái)不小的挑戰(zhàn)。如圖所示,當(dāng)小明給自己的女朋友小紅情人節(jié)發(fā)了520的紅包,但是此時(shí)女朋友卻沒(méi)有收到感到非常生氣,小明也很委屈,明明剛發(fā)的紅包去哪里呢?



          其實(shí)是因?yàn)樾∶靼l(fā)紅包之后寫入的數(shù)據(jù)節(jié)點(diǎn)和小紅讀取的數(shù)據(jù)節(jié)點(diǎn)不一致,并且小明發(fā)送的紅包的數(shù)據(jù)節(jié)點(diǎn)并沒(méi)有及時(shí)同步到小紅讀取的數(shù)據(jù)節(jié)點(diǎn)。


          下面我們從數(shù)據(jù)存儲(chǔ)讀取的角度分析可能帶來(lái)的問(wèn)題以及解決方法。




          02



          數(shù)據(jù)存儲(chǔ)一致性

          在討論這個(gè)問(wèn)題我們先來(lái)想下,分布式環(huán)境下導(dǎo)致存儲(chǔ)不穩(wěn)定的本質(zhì)原因其實(shí)是“無(wú)法讀到正確的寫。那么為了解決“讀正確的寫這個(gè)問(wèn)題,就很有必要討論下分布式環(huán)境下的存儲(chǔ)節(jié)點(diǎn)之間是如何相互工作的,因?yàn)橹挥姓莆樟苏_的數(shù)據(jù)流向,才能更好地剖析問(wèn)題。


          我們?cè)賮?lái)思考一個(gè)問(wèn)題,為什么單體應(yīng)用不存在這個(gè)問(wèn)題?這是因?yàn)閱误w情況下數(shù)據(jù)的存儲(chǔ)和讀取的節(jié)點(diǎn)是唯一的,但是在分布式的場(chǎng)景下,情況就不一樣了,多個(gè)節(jié)點(diǎn)之間就涉及到數(shù)據(jù)同步問(wèn)題,而數(shù)據(jù)同步問(wèn)題又和服務(wù)的部署架構(gòu)有關(guān)系,因此我們從服務(wù)架構(gòu)入手來(lái)分類討論。


             2.1 主從架構(gòu)



          主從架構(gòu)是數(shù)據(jù)庫(kù)常見的部署架構(gòu),即主節(jié)點(diǎn)負(fù)責(zé)寫入數(shù)據(jù),從節(jié)點(diǎn)來(lái)分擔(dān)讀流量,在這種架構(gòu)模式下,主從間的數(shù)據(jù)同步存在三種方式:

          • 同步復(fù)制;

          • 半同步復(fù)制;

          • 異步復(fù)制。


             2.1.1 同步復(fù)制



          同步復(fù)制指的是數(shù)據(jù)在主節(jié)點(diǎn)寫入成功之后,還需要確保各個(gè)從節(jié)點(diǎn)同步數(shù)據(jù)成功之后才向上游返回成功 ack。一般用于對(duì)數(shù)據(jù)可靠性要求較高的場(chǎng)景,如金融級(jí)的數(shù)據(jù)庫(kù) tdsql,生產(chǎn)環(huán)境一般使用一主兩備強(qiáng)同步的方式,這種同步復(fù)制的方式存在相應(yīng)的優(yōu)缺點(diǎn):

          • 優(yōu)點(diǎn):主從間的數(shù)據(jù)同步強(qiáng)一致,數(shù)據(jù)可靠性高。

          • 缺點(diǎn):數(shù)據(jù)同步環(huán)境對(duì)網(wǎng)絡(luò)的延時(shí)要求較高,并且從節(jié)點(diǎn)越多,寫入的效率會(huì)越低,受網(wǎng)絡(luò)波動(dòng)影響越大,相比于半同步和異步復(fù)制來(lái)說(shuō),數(shù)據(jù)復(fù)制效率較低。


          因此在這種同步模式下,數(shù)據(jù)寫入和讀取是對(duì)等的,因?yàn)橐坏┗貜?fù)了成功的 ack 之后,代表主從間的數(shù)據(jù)保持一致,數(shù)據(jù)穩(wěn)定性高。


             2.1.2 半同步復(fù)制



          半同步復(fù)制指的是數(shù)據(jù)在主節(jié)點(diǎn)寫入成功之后,從節(jié)點(diǎn)同步只要同步成功一個(gè)即返回成功 ack。一般用于對(duì)數(shù)據(jù)寫入效率要求較高的場(chǎng)景,據(jù)作者了解,shopee 的 db 同步主要采用這種半同步復(fù)制的方式,這種同步復(fù)制方式存在相應(yīng)的優(yōu)缺點(diǎn)

          • 優(yōu)點(diǎn):主從同步效率高,對(duì)網(wǎng)絡(luò)延時(shí)較不敏感。

          • 缺點(diǎn):在數(shù)據(jù)同步過(guò)程中,由于只要一個(gè)節(jié)點(diǎn)同步成功即算寫入成功,如果此時(shí)其他數(shù)據(jù)節(jié)點(diǎn)異步復(fù)制失敗,恰好此時(shí)路由到該節(jié)點(diǎn),可能出現(xiàn)幻寫(即剛寫入的數(shù)據(jù)再讀取的時(shí)候發(fā)生丟失),數(shù)據(jù)可靠性較低。


          因此在此同步模式下,數(shù)據(jù)的一致性不高,只能通過(guò)未同步節(jié)點(diǎn)異步追趕主節(jié)點(diǎn)日志來(lái)達(dá)到最終數(shù)據(jù)一致的目的,此時(shí)如果對(duì)于數(shù)據(jù)一致性要求較高的場(chǎng)景,可以通過(guò)“主寫主讀”的方式來(lái)實(shí)現(xiàn)。半同步復(fù)制通過(guò)犧牲了一部分?jǐn)?shù)據(jù)穩(wěn)定性來(lái)?yè)Q取同步寫入的高效,是比較好的折中方式。


             2.1.3 異步復(fù)制



          異步復(fù)制指的是數(shù)據(jù)在主節(jié)點(diǎn)寫入成功后立即返回,從節(jié)點(diǎn)異步復(fù)制主節(jié)點(diǎn)的數(shù)據(jù)。一般用于對(duì)數(shù)據(jù)寫入效率要求較高的場(chǎng)景,如此時(shí) db 做災(zāi)備以及異地多活場(chǎng)景下,可能涉及到跨區(qū)的數(shù)據(jù)復(fù)制,可以采用這種方式進(jìn)行同步:

          • 優(yōu)點(diǎn):主從同步效率很高,從節(jié)點(diǎn)的網(wǎng)絡(luò)延時(shí)對(duì)主節(jié)點(diǎn)的寫入完全沒(méi)有影響。

          • 缺點(diǎn):從節(jié)點(diǎn)無(wú)法和主節(jié)點(diǎn)保持完全同步,通過(guò)異步同步的方式很有可能出現(xiàn)主從間數(shù)據(jù)不一致的場(chǎng)景。


          因此在這種同步模式下,數(shù)據(jù)的可靠性較低,如果對(duì)于數(shù)據(jù)一致性要求較高的場(chǎng)景,同樣可以通過(guò)“主寫主讀”的方式來(lái)實(shí)現(xiàn)。


          通過(guò)上述的討論可得主從模式下數(shù)據(jù)的可靠性主要是通過(guò)主從間的數(shù)據(jù)復(fù)制機(jī)制來(lái)保證的,同時(shí),主節(jié)點(diǎn)存在單點(diǎn)問(wèn)題,承載了寫入流量。那么為了保證數(shù)據(jù)的一致性,我們應(yīng)該考慮如何處理節(jié)點(diǎn)失效?


             2.1.4 處理節(jié)點(diǎn)失效


          這個(gè)問(wèn)題我們可以從兩方面考慮:


          從節(jié)點(diǎn)失效:追趕主節(jié)點(diǎn)。這里我覺(jué)得在全同步模式下可以借鑒 kafka 的 ISR 機(jī)制,去維護(hù)一個(gè)網(wǎng)絡(luò)效率高的同步節(jié)點(diǎn)隊(duì)列,當(dāng)延時(shí)較大時(shí)主動(dòng)剔除該隊(duì)列并進(jìn)行數(shù)據(jù)追趕,等到追趕完成之后再加入到該隊(duì)列中。



          主節(jié)點(diǎn)失效:重新選主。重新選主的話也需要注意以下幾個(gè)問(wèn)題。選舉的時(shí)候可能會(huì)導(dǎo)致選舉的節(jié)點(diǎn)有數(shù)據(jù)缺失問(wèn)題;還有可能存在腦裂問(wèn)題,參考 Redis 解決腦裂的方式,通過(guò)參數(shù)配置 min-slaves-to-write(最小從服務(wù)器數(shù)) 和 min-slaves-max-lag(從連接的最大延遲時(shí)間)。


          • min-slaves-to-write 是指主庫(kù)最少得有 N 個(gè)健康的從庫(kù)存活才能執(zhí)行寫命令。這個(gè)配置雖然不能保證 N 個(gè)從庫(kù)都一定能接收到主庫(kù)的寫操作,但是能避免當(dāng)沒(méi)有足夠健康的從庫(kù)時(shí),主庫(kù)無(wú)法正常寫入,以此來(lái)避免數(shù)據(jù)的丟失 ,如果設(shè)置為 0 則表示關(guān)閉該功能。

          • min-slaves-max-lag :是指從庫(kù)和主庫(kù)進(jìn)行數(shù)據(jù)復(fù)制時(shí)的 ACK 消息延遲的最大時(shí)間;可以確保從庫(kù)在指定的時(shí)間內(nèi),如果 ACK 時(shí)間沒(méi)在規(guī)定時(shí)間內(nèi),則拒絕寫入。


             2.2 主主架構(gòu)



          主主架構(gòu)解決了主從架構(gòu)下單點(diǎn)寫的問(wèn)題,可以由多個(gè)節(jié)點(diǎn)承載著寫和讀的流量,并且完成從節(jié)點(diǎn)的數(shù)據(jù)同步動(dòng)作,常見的應(yīng)用場(chǎng)景主要見于:

          • 多數(shù)據(jù)中心。為了容忍整個(gè)數(shù)據(jù)中心級(jí)別故障或者更接近用戶,可以把數(shù)據(jù)庫(kù)的副本橫跨多個(gè)數(shù)據(jù)中心。

          • 離線客戶端操作。如手機(jī)或其他電子設(shè)備的筆記軟件設(shè)備,能夠在多端寫入以及在多端進(jìn)行數(shù)據(jù)同步。

          • 協(xié)同編輯。如在線文檔操作,多用戶同時(shí)編輯文檔,當(dāng)用戶編輯更改,會(huì)立即在其他用戶端數(shù)據(jù)界面生效。


          在這種架構(gòu)下數(shù)據(jù)脫離了單節(jié)點(diǎn)寫入的控制,但是帶來(lái)的副作用就是如何協(xié)同多主間的數(shù)據(jù)同步問(wèn)題,數(shù)據(jù)的寫入得到了保障,但是數(shù)據(jù)間的同步以及沖突卻成了另外一個(gè)我們需要解決的棘手的問(wèn)題。


             2.2.1 沖突解決


          這里我們可以解決思路可以從這幾方面入手

          • 處理寫沖突。在發(fā)生同時(shí)寫入某行的數(shù)據(jù)沖突情況下能夠有機(jī)制及時(shí)發(fā)現(xiàn),并且阻塞其他的寫請(qǐng)求,直到該寫入完成再進(jìn)行后續(xù)節(jié)點(diǎn)的寫入,但是這么做會(huì)極大降低并發(fā)效率,如果是多設(shè)備的數(shù)據(jù)同步場(chǎng)景下,沖突概率不大,因?yàn)槔碚撋嫌脩舢?dāng)前時(shí)間只會(huì)針對(duì)某個(gè)設(shè)備下進(jìn)行編輯;但是對(duì)于協(xié)同編輯的場(chǎng)景下,這種沖突的概率就很大,因此寫入的效率就會(huì)大打折扣。

          • 避免沖突。解決沖突最好的方式就是避免沖突,這種思想在很多產(chǎn)品上都可以得以體現(xiàn),如 MySQL的 mvcc 模式,在事務(wù)中讀取的是 mvcc 的快照,隔離了不同事務(wù)之間對(duì)于動(dòng)態(tài)更改數(shù)據(jù)的訪問(wèn),轉(zhuǎn)而請(qǐng)求快照,避免了沖突場(chǎng)景下的數(shù)據(jù)讀取,只在數(shù)據(jù)提交的時(shí)候?qū)Ω男械臎_突以及一致性約束進(jìn)行檢測(cè)。同樣,在多數(shù)據(jù)中心的場(chǎng)景下,我們也可以將用戶路由到最近的數(shù)據(jù)中心進(jìn)行寫入,以此來(lái)降低數(shù)據(jù)沖突的概率。

          • 一致性狀態(tài)收斂。理想情況下,我們還是希望數(shù)據(jù)能夠?qū)ν獗3忠恢拢敲醋钪苯拥姆绞骄褪墙鉀Q沖突,即在用戶提交數(shù)據(jù)時(shí)由服務(wù)端檢測(cè)各節(jié)點(diǎn)之間的數(shù)據(jù)差異,主動(dòng)或者被動(dòng)進(jìn)行數(shù)據(jù)合并,可以使用以下幾種方式:

            1. 給寫入分配時(shí)間戳,并且以后寫入的數(shù)據(jù)為準(zhǔn)。

            2. 為每個(gè)同步節(jié)點(diǎn)分配唯一 ID,指定規(guī)則如序號(hào)高的副本始終優(yōu)先于序號(hào)低副本的寫入。

            3. 按照預(yù)定義的合并規(guī)則自動(dòng)將數(shù)據(jù)進(jìn)行合并。

            4. 將合并控制權(quán)交給用戶,讓用戶自行決定數(shù)據(jù)合并。


          由上述分析可得,主主架構(gòu)下雖然能夠解決單節(jié)點(diǎn)寫入的問(wèn)題,但是問(wèn)題矛盾轉(zhuǎn)移為主主間數(shù)據(jù)沖突解決的問(wèn)題,這個(gè)問(wèn)題雖然也有相應(yīng)的解決方案,但是不同的解決方案只能針對(duì)部分場(chǎng)景進(jìn)行解決,因此開發(fā)者在使用這種架構(gòu)的數(shù)據(jù)存儲(chǔ)方式的時(shí)候,應(yīng)當(dāng)根據(jù)自身的業(yè)務(wù)選擇不同的策略解決。


             2.3 無(wú)主架構(gòu)



          無(wú)主結(jié)構(gòu)則更為激進(jìn),相比于主從和主主架構(gòu),放棄主節(jié)點(diǎn),允許任何副本節(jié)點(diǎn)承載寫和讀的流量,寫入的時(shí)候只要保證寫入“大多數(shù)成功”即認(rèn)為寫入成功,那么這時(shí)候假設(shè)其中的一個(gè)節(jié)點(diǎn)寫入失敗,接著讀取時(shí)又恰巧讀取到了該節(jié)點(diǎn)的數(shù)據(jù),是不是就會(huì)發(fā)生數(shù)據(jù)缺失問(wèn)題?為了解決這個(gè)問(wèn)題,就需要我們讀取數(shù)據(jù)的時(shí)候不僅從一個(gè)節(jié)點(diǎn)進(jìn)行讀取,而是從多個(gè)節(jié)點(diǎn)進(jìn)行,并且寫入的數(shù)據(jù)中附帶版本號(hào),只要我們能夠保證絕大部分節(jié)點(diǎn)可信任,就可以獲取到正確的數(shù)據(jù)。


          所以在無(wú)主架構(gòu)下,主要矛盾轉(zhuǎn)化為如何保證寫入和讀取正確的問(wèn)題。


             2.3.1 讀寫 quorum



          即通過(guò)寫入一定冗余節(jié)點(diǎn)的數(shù)據(jù)來(lái)保證數(shù)據(jù)的可靠性。即如果有 n 個(gè)副本,寫入需要 w 個(gè)節(jié)點(diǎn)確認(rèn),讀取必須至少查詢 r 個(gè)節(jié)點(diǎn),則只要滿足 w+r>n 的條件,那么讀取的節(jié)點(diǎn)中一定會(huì)包含最新值。這個(gè)結(jié)論舉個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明,如圖所示,一共五個(gè)節(jié)點(diǎn),w 和 r 都為3,這樣就可以保證讀取的時(shí)候無(wú)論是讀取哪幾個(gè)節(jié)點(diǎn),都至少有一個(gè)節(jié)點(diǎn)能讀到寫入成功的對(duì)應(yīng)的節(jié)點(diǎn)。也就是只要我們能保證讀和寫的節(jié)點(diǎn)之間存在交叉即可。


             2.3.2 quorum 問(wèn)題


          看似這個(gè)方案好像完美解決了數(shù)據(jù)一致性問(wèn)題,但是我們仔細(xì)思考下,還是存在一定的問(wèn)題。

          1. 當(dāng)此時(shí)數(shù)據(jù)節(jié)點(diǎn)出現(xiàn)宕機(jī)的情況下,即 n<r 的情況,服務(wù)就不可用了,根據(jù) cap 理論,只能夠?qū)崿F(xiàn) cp,犧牲可用性來(lái)滿足一致性。

          2. 即使在 w+r>n 的場(chǎng)景下,也可能存在數(shù)據(jù)返回異常的情況。

            • 寫操作同時(shí)發(fā)生,無(wú)法確定先后順序,因?yàn)榭赡艽嬖跁r(shí)鐘偏移的情況。

            • 寫和讀操作同時(shí)發(fā)生,寫操作可能僅在一部分副本上完成,此時(shí),讀取時(shí)返回舊值和新值不確定。

            • 寫操作在節(jié)點(diǎn)中部分成功,部分失敗,但是由于已成功的數(shù)據(jù)無(wú)法回滾,可能引入臟數(shù)據(jù)。


          當(dāng)然,我們也可以采用寬松的 quorum 的方式,即在寫入的節(jié)點(diǎn)不滿足w的情況下,增加 n 意外的臨時(shí)節(jié)點(diǎn),再在網(wǎng)絡(luò)回復(fù)的時(shí)候把臨時(shí)節(jié)點(diǎn)的數(shù)據(jù)同步到主節(jié)點(diǎn)上,但是這樣就犧牲了數(shù)據(jù)一致性來(lái)滿足可用性。所以收到 CAP 理論的限制,無(wú)論怎么樣都無(wú)法同時(shí)滿足,只能根據(jù)具體的實(shí)際情況來(lái)做取舍。


          由上述分析可得,在無(wú)主的情況下,數(shù)據(jù)的寫入雖然不受到單節(jié)點(diǎn)的限制,但是在極端場(chǎng)景下同樣無(wú)法保障數(shù)據(jù)的可靠性,需要能夠容忍數(shù)據(jù)不一致的場(chǎng)景。




          03



          總結(jié)

          我們?yōu)榱颂骄糠植际江h(huán)境下的數(shù)據(jù)一致性,從數(shù)據(jù)架構(gòu)入手,分別探究了

          • 主從架構(gòu)。

          • 主主架構(gòu)。

          • 無(wú)主架構(gòu)。


          這三種架構(gòu)下數(shù)據(jù)是否能夠保持寫入和讀取的一致,綜上可知,每個(gè)方法都有對(duì)應(yīng)的優(yōu)缺點(diǎn),在實(shí)際的開發(fā)過(guò)程中,我們應(yīng)當(dāng)要能夠?qū)嶋H的業(yè)務(wù)情況,有所取舍地選擇合適的架構(gòu),并且在實(shí)現(xiàn)的過(guò)程中注意這些可能出現(xiàn)的數(shù)據(jù)坑點(diǎn),這樣才能做到有的放矢,寫出更加魯棒的軟件。


          -End-
          原創(chuàng)作者 | 李濱

           


          你還知道哪些保證分布式系統(tǒng)數(shù)據(jù)一致性的方案?歡迎評(píng)論留言。我們將選取1則優(yōu)質(zhì)的評(píng)論,送出騰訊Q哥公仔1個(gè)(見下圖)。4月3日中午12點(diǎn)開獎(jiǎng)。


          ????歡迎加入騰訊云開發(fā)者社群,享前沿資訊、大咖干貨,找興趣搭子,交同城好友,更有鵝廠招聘機(jī)會(huì)、限量周邊好禮等你來(lái)~


          (長(zhǎng)按圖片立即掃碼)





          瀏覽 16
          點(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>
                  ww激情| 欧美成人手机免费在线观看 | 欧洲精品在线观看 | 婷婷国产在线视频 | 我要看日本一级片 |