自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何平衡存儲(chǔ)系統(tǒng)的一致性和可用性?

開發(fā) 架構(gòu)
在分布式存儲(chǔ)系統(tǒng)中,讓系統(tǒng)中多個(gè)實(shí)例的狀態(tài)保持一致,是一個(gè)比較難處理的問(wèn)題。尤其是當(dāng)系統(tǒng)出現(xiàn)故障時(shí),系統(tǒng)能否始終保持一致性,很大程度上影響了系統(tǒng)的可用性和數(shù)據(jù)的可靠性。

在分布式存儲(chǔ)系統(tǒng)中,讓系統(tǒng)中多個(gè)實(shí)例的狀態(tài)保持一致,是一個(gè)比較難處理的問(wèn)題。尤其是當(dāng)系統(tǒng)出現(xiàn)故障時(shí),系統(tǒng)能否始終保持一致性,很大程度上影響了系統(tǒng)的可用性和數(shù)據(jù)的可靠性。

典型的由不一致導(dǎo)致的重大事故是這樣的:正常情況下,系統(tǒng)通過(guò)某種數(shù)據(jù)同步機(jī)制保持各實(shí)例上狀態(tài)的一致性,當(dāng)發(fā)生實(shí)例宕機(jī)、網(wǎng)絡(luò)分區(qū)等故障時(shí),這種同步機(jī)制無(wú)法正常工作,一致性被打破。

這種情況下,出現(xiàn)了多份不一致的狀態(tài)數(shù)據(jù),系統(tǒng)很難自動(dòng)去判斷到底哪份狀態(tài)數(shù)據(jù)才是“正確的”,也就沒(méi)有辦法自動(dòng)恢復(fù)。更糟糕的是,一旦這種不一致的狀態(tài)被其它系統(tǒng)讀取,錯(cuò)誤的狀態(tài)將被傳遞到其它系統(tǒng)中,造成不可預(yù)期的結(jié)果。

這種復(fù)雜的數(shù)據(jù)錯(cuò)誤,即使人工處理也是非常難恢復(fù),往往恢復(fù)時(shí)間需要幾小時(shí)或幾天,嚴(yán)重情況下甚至于無(wú)法恢復(fù)。

可以看出,在故障情況下仍然保持一致性,是系統(tǒng)能快速?gòu)墓收现谢謴?fù)的前提條件,有助于提升系統(tǒng)的可用性。但為了保證一致性,在數(shù)據(jù)更新時(shí),往往需要協(xié)調(diào)參與的各個(gè)模塊,確保它們同步更新。比如,使用各種分布式事務(wù)。

但這會(huì)導(dǎo)致這些模塊在可用性上緊密耦合在一起,反而降低了系統(tǒng)的可用性。這種場(chǎng)景下,可用性和一致性又存在矛盾。

本文從高可用視角來(lái)重新審視數(shù)據(jù)一致性問(wèn)題,討論如何在可用性和一致性上取得相對(duì)的平衡。

01 如無(wú)必要,勿增副本

在考慮如何平衡一致性與可用性之前,最重要的是要意識(shí)到,在分布式系統(tǒng)中解決一致性問(wèn)題需要付出非常大的代價(jià),這些代價(jià)可能包括:可用性降低、性能下降、用戶體驗(yàn)變差或者是極大的增加了系統(tǒng)的復(fù)雜度。

因此,不要人為制造一致性難題。但是,很多情況下,因?yàn)槿鄙龠@方面的意識(shí),我們無(wú)意間為系統(tǒng)制造了本無(wú)必要的一致性難題,然后又付出了巨大的代價(jià)去解決這個(gè)難題,得不償失。

為系統(tǒng)中的狀態(tài)數(shù)據(jù)設(shè)計(jì)多個(gè)副本的情況并不罕見,常見的多副本設(shè)計(jì)包括:

  • 以不同格式或數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)多個(gè)副本。
  • 在不同類型的外部存儲(chǔ)中存儲(chǔ)多個(gè)副本。
  • 在本地磁盤或內(nèi)存中緩存數(shù)據(jù)的副本。

以上這些都是我們時(shí)常會(huì)用到的設(shè)計(jì)模式,難道說(shuō)它們都是“不好的設(shè)計(jì)”么?

當(dāng)然不是這樣的。

架構(gòu)設(shè)計(jì)是平衡的藝術(shù),當(dāng)架構(gòu)師選擇某種設(shè)計(jì)或架構(gòu)時(shí),一定要充分了解當(dāng)前選擇的優(yōu)勢(shì)和代價(jià),確保優(yōu)點(diǎn)是我們所需要的,代價(jià)是我們能接受的。這樣的設(shè)計(jì)才是在當(dāng)前場(chǎng)景下最優(yōu)的選擇。

為數(shù)據(jù)增加副本會(huì)帶來(lái)一致性難題,開發(fā)者需要為此付出巨大的代價(jià)去維護(hù)數(shù)據(jù)一致性。所以,在設(shè)計(jì)過(guò)程中需要慎重考慮,為系統(tǒng)增加副本所帶來(lái)的收益和付出的代價(jià),二者相比是不是值得做出這樣的選擇。

我們需要避免的是,在設(shè)計(jì)過(guò)程中未經(jīng)仔細(xì)思考隨意增加副本的行為。

以下是幾個(gè)常見的錯(cuò)誤示例:

  • 僅僅是為了寫代碼的時(shí)候更方便地讀取數(shù)據(jù),就隨意增加副本。比如,為了便于查詢,將數(shù)據(jù)庫(kù)中A表中的部分字段,在B表中也保存一份。
  • 系統(tǒng)中存在多個(gè)外部存儲(chǔ),為了讀寫方便,在每個(gè)外部存儲(chǔ)都保存一份數(shù)據(jù)副本。比如,集群的元數(shù)據(jù)保存在ZooKeeper中,為了方便管理控制臺(tái)操作,也在MySQL中保存一份同樣的數(shù)據(jù)。
  • 不考慮系統(tǒng)的性能實(shí)際要求,為了讓系統(tǒng)速度更快一些,在Redis和內(nèi)存中緩存數(shù)據(jù)。

02 一致性與可用性的矛盾

在現(xiàn)有硬件技術(shù)條件下,對(duì)分布式系統(tǒng)中每個(gè)節(jié)點(diǎn)更新操作,總會(huì)有先后,不可能做到絕對(duì)的“同時(shí)”,也就無(wú)法保證系統(tǒng)的多個(gè)副本在“任何時(shí)刻”狀態(tài)都相同。

因此,這里我們討論的一致性是,系統(tǒng)作為一個(gè)整體對(duì)外部所表現(xiàn)出的一致性。換句話說(shuō)就是,分布式系統(tǒng)內(nèi)部可以存在不一致的狀態(tài),但只要這種不一致的狀態(tài)對(duì)外部是不可見的,那就可以認(rèn)為這個(gè)系統(tǒng)具備一致性。

在分布式系統(tǒng)中,既要保證高可用又要保證一致性是幾乎不可能實(shí)現(xiàn)的。我們把分布式系統(tǒng)抽象成最簡(jiǎn)單的模型:一個(gè)只有兩個(gè)有狀態(tài)節(jié)點(diǎn)系統(tǒng)。然后在這個(gè)最簡(jiǎn)模型下來(lái)分析一致性問(wèn)題:如何保證這兩個(gè)節(jié)點(diǎn)上的狀態(tài),在任何時(shí)刻都是相同的?

即使在這樣一個(gè)最簡(jiǎn)模型下,保持一致性仍然面臨下面的3個(gè)難題。

第一個(gè)難題是,如何處理更新操作失敗的情況。

要保持兩個(gè)節(jié)點(diǎn)上狀態(tài)的一致性,理論上需要每次更新狀態(tài)時(shí)同步更新兩個(gè)節(jié)點(diǎn)上的狀態(tài)。如果某一個(gè)節(jié)點(diǎn)上的更新操作失敗了,系統(tǒng)將變成如下不一致的狀態(tài):一個(gè)節(jié)點(diǎn)更新成功,而另外一個(gè)節(jié)點(diǎn)更新失敗。

在這種情況下,還要保持系統(tǒng)的一致性,就需要將這種不一致狀態(tài)隔離在系統(tǒng)內(nèi)部,不能讓外部系統(tǒng)感知,并且盡快修復(fù)不一致的狀態(tài)。

要修復(fù)這種不一致狀態(tài),一般有兩種方法,分別是重試和回滾。

  • 重試指的是,讓失敗的節(jié)點(diǎn)重新執(zhí)行更新操作。如果重試成功,系統(tǒng)將重新回到一致的狀態(tài)。
  • 回滾指的是,讓之前更新成功的節(jié)點(diǎn)執(zhí)行回滾操作,回到更新前的狀態(tài),也可以讓系統(tǒng)重新回到一致狀態(tài)。

但重試和回滾的實(shí)現(xiàn)代價(jià)都很大。

通過(guò)重試來(lái)解決一致性的前提是,被重試的更新操作必須具備冪等性和原子性。

  • 冪等性,可以保證多次重試同一個(gè)更新操作不會(huì)改變狀態(tài)的正確性;
  • 原子性,則可以避免在更新具有復(fù)雜數(shù)據(jù)結(jié)構(gòu)的狀態(tài)失敗時(shí),只更新了部分狀態(tài)的尷尬局面。

如果系統(tǒng)的狀態(tài)不是保存在關(guān)系型數(shù)據(jù)庫(kù)中,要實(shí)現(xiàn)冪等性和原子性其實(shí)很不容易。

實(shí)現(xiàn)回滾同樣要保證原子性,此外為了能將狀態(tài)恢復(fù)到更新之前,需要在執(zhí)行更新操作之前記錄原始狀態(tài),系統(tǒng)還要考慮如何處理回滾失敗的問(wèn)題。

第二個(gè)難題是,如何在其中一個(gè)節(jié)點(diǎn)不可用的情況下保證系統(tǒng)一致性。

當(dāng)系統(tǒng)其中的一個(gè)節(jié)點(diǎn)不可用時(shí),另外一個(gè)節(jié)點(diǎn)仍然可以提供讀寫服務(wù)。當(dāng)故障節(jié)點(diǎn)恢復(fù)后,理論上只要把狀態(tài)數(shù)據(jù)從可用節(jié)點(diǎn)同步到之前故障的節(jié)點(diǎn)上,系統(tǒng)就可以重新回到一致性狀態(tài)了。而在現(xiàn)實(shí)中實(shí)現(xiàn)好數(shù)據(jù)同步,既要做到快速同步,又要保證不重不漏,難度和代價(jià)都比較大。

最簡(jiǎn)單的方法是全量數(shù)據(jù)同步,清空故障節(jié)點(diǎn)上的狀態(tài)數(shù)據(jù),然后將可用節(jié)點(diǎn)上的狀態(tài)數(shù)據(jù)全部復(fù)制到故障節(jié)點(diǎn)上。全量同步相對(duì)比較耗時(shí),如果數(shù)據(jù)量比較大,就必須采用增量同步的方法。

而增量同步,則需要精準(zhǔn)地界定出哪些數(shù)據(jù)屬于“增量數(shù)據(jù)”。這對(duì)于大多數(shù)采用多線程并行處理請(qǐng)求的服務(wù)來(lái)說(shuō),幾乎不可能實(shí)現(xiàn)。同時(shí),另一個(gè)不得不考慮的極端情況是,如果在一段時(shí)間內(nèi)兩個(gè)節(jié)點(diǎn)交替多次出現(xiàn)不可用的情況,系統(tǒng)將很難判定哪個(gè)節(jié)點(diǎn)上的狀態(tài)才是“正確可信的狀態(tài)”,也就無(wú)法恢復(fù)系統(tǒng)的一致性狀態(tài)。

第三個(gè)難題是,如何在網(wǎng)絡(luò)分區(qū)情況下保證系統(tǒng)的一致性。

網(wǎng)絡(luò)分區(qū),指的是由于網(wǎng)絡(luò)設(shè)備故障,造成網(wǎng)絡(luò)分裂為多個(gè)獨(dú)立的區(qū)域。典型場(chǎng)景是兩個(gè)機(jī)房間的網(wǎng)絡(luò)中斷,這兩個(gè)機(jī)房就形成了兩個(gè)互不聯(lián)通的分區(qū)。

假設(shè)發(fā)生了網(wǎng)絡(luò)分區(qū),系統(tǒng)的兩個(gè)節(jié)點(diǎn)恰巧分別位于不同分區(qū),這種情況下,雖然沒(méi)有節(jié)點(diǎn)不可用,但節(jié)點(diǎn)間無(wú)法通信,也就無(wú)法保證系統(tǒng)一致性。如果系統(tǒng)不能容忍“不一致”,唯一的辦法就是在網(wǎng)絡(luò)分區(qū)期間停止對(duì)外提供服務(wù),也就是說(shuō)需要犧牲“可用性”。

上面我們討論的情況,就是著名的CAP理論的一種典型場(chǎng)景:在網(wǎng)絡(luò)分區(qū)的情況下,一致性和可用性只能二選其一。

鑒于一致性與可用性存在沖突,以及實(shí)現(xiàn)一致性的代價(jià)過(guò)高這兩個(gè)原因,在設(shè)計(jì)分布式系統(tǒng)時(shí),放棄對(duì)嚴(yán)格一致性的約束,讓系統(tǒng)去適應(yīng)相對(duì)寬松一致性,從而在一致性、可用性和性能上取得相對(duì)可接受的平衡,是更加理性的選擇。

所謂“寬松一致”,是在隔離性和性能等方面適當(dāng)放寬要求后的一系列降級(jí)版一致性。相對(duì)的,我們之前討論的一致性,也被稱為“強(qiáng)一致”。最終一致是普遍采用的一種寬松一致。

比如上面的例子,在網(wǎng)絡(luò)分區(qū)的情況下,如果可以接受最終一致,則系統(tǒng)仍然可以在其中的一個(gè)分區(qū)提供讀寫服務(wù),另一個(gè)分區(qū)提供只讀服務(wù),極大增強(qiáng)系統(tǒng)的可用性。只要待網(wǎng)絡(luò)故障結(jié)束后,再通過(guò)單向數(shù)據(jù)同步即可恢復(fù)系統(tǒng)一致性。

03 在一致性與可用性之間保持平衡

犧牲強(qiáng)一致后,當(dāng)系統(tǒng)故障時(shí),由于系統(tǒng)存在多個(gè)副本,就比較容易繼續(xù)維持可用性。無(wú)論是發(fā)生網(wǎng)絡(luò)故障還是服務(wù)器宕機(jī),只要調(diào)用端還能訪問(wèn)某個(gè)存活的副本,系統(tǒng)仍然可以提供服務(wù)。

BASE給出了一種平衡一致性和可用性的策略,這種策略適用范圍廣泛,實(shí)現(xiàn)難度不大,在一致性和可用性上都有不錯(cuò)的表現(xiàn)。BASE是“基本可用(Basically Available)”“軟狀態(tài)(Soft State)”和“最終一致(Eventually Consistent)”這三個(gè)詞的縮寫。

其中:

  • 基本可用是對(duì)可用性的妥協(xié),指的是在故障時(shí),系統(tǒng)以響應(yīng)時(shí)間變長(zhǎng)、部分功能不可用或者部分請(qǐng)求失敗為代價(jià),換取整個(gè)系統(tǒng)仍然可以提供基本的服務(wù)能力。
  • 軟狀態(tài)和最終一致則是對(duì)一致性的妥協(xié)。具體地說(shuō),就是犧牲了原子性和隔離性,允許系統(tǒng)內(nèi)出現(xiàn)外部可見的“中間狀態(tài)”,但需要在短時(shí)間內(nèi)恢復(fù)為一致狀態(tài),達(dá)成最終一致。

在多個(gè)組件構(gòu)成的分布式系統(tǒng)中,如果某個(gè)組件在設(shè)計(jì)上降低了可用性和一致性的等級(jí),依賴這個(gè)組件的其它組件或外部服務(wù)為了能夠兼容這種降級(jí)設(shè)計(jì),往往需要付出額外的代價(jià)。因此,設(shè)計(jì)者需要針對(duì)系統(tǒng)的實(shí)際情況來(lái)權(quán)衡決策,謹(jǐn)慎降級(jí)可用性和一致性?;究捎貌坏扔诓豢捎?,最終一致也不等于不一致。

接下來(lái)介紹實(shí)踐BASE理論的常用方法和常見誤區(qū)。

“最終一致”允許不一致的中間狀態(tài)被外部可見,但需要在短時(shí)間內(nèi)恢復(fù)為一致狀態(tài)。這里面的“短時(shí)間”能否量化呢?

要回答這個(gè)問(wèn)題,我們需要分系統(tǒng)正常和故障二種情況來(lái)分別討論。

在系統(tǒng)正常時(shí),達(dá)成最終一致的時(shí)間要求是“在系統(tǒng)外部幾乎不可感知”,具體來(lái)說(shuō)應(yīng)該與需要同步狀態(tài)的節(jié)點(diǎn)之間的網(wǎng)絡(luò)時(shí)延差不多。比如,如果系統(tǒng)的節(jié)點(diǎn)都部署在同一個(gè)數(shù)據(jù)中心內(nèi),達(dá)成最終一致的時(shí)延不應(yīng)超過(guò)幾個(gè)毫秒;對(duì)于一個(gè)全球部署的系統(tǒng),達(dá)成最終一致的時(shí)延可能需要幾十至幾百毫秒。

在系統(tǒng)發(fā)生網(wǎng)絡(luò)分區(qū)故障時(shí),為了盡可能保證系統(tǒng)的可用性,需要進(jìn)一步犧牲達(dá)成最終一致的時(shí)延,最長(zhǎng)可能需要等到故障恢復(fù)后系統(tǒng)才能達(dá)成最終一致。

▲圖1 系統(tǒng)故障時(shí)需要更長(zhǎng)的時(shí)間達(dá)成最終一致

犧牲一致性需要守住兩個(gè)底線:防止腦裂和要保證單調(diào)讀寫。

我們首先來(lái)討論底線一:防止腦裂。

例如,傳統(tǒng)MySQL主從結(jié)構(gòu)中,如果主庫(kù)宕機(jī),或者網(wǎng)絡(luò)分區(qū)導(dǎo)致無(wú)法訪問(wèn)主庫(kù),也不應(yīng)該去更新從庫(kù)中的數(shù)據(jù),否則在故障結(jié)束后,系統(tǒng)面對(duì)主庫(kù)和從庫(kù)二份不一樣的數(shù)據(jù),是無(wú)法自動(dòng)恢復(fù)的。這種情況被稱為“腦裂(Split-brain)”,出現(xiàn)腦裂后,理論上系統(tǒng)的一致性不可恢復(fù)。

工程實(shí)踐中,一般都需要人工介入,借助數(shù)據(jù)的業(yè)務(wù)屬性(比如,同一訂單支付操作一定早于發(fā)貨操作,則可以判斷“已發(fā)貨”狀態(tài)是比“已支付”更新的狀態(tài)),才有可能完成數(shù)據(jù)的一致性修復(fù)。

特別注意的是,不應(yīng)該以狀態(tài)更新的時(shí)間戳來(lái)判斷狀態(tài)數(shù)據(jù)的新舊并用于恢復(fù)一致性。狀態(tài)數(shù)據(jù)中記錄的時(shí)間戳來(lái)自客戶端或服務(wù)端應(yīng)用所在的多個(gè)節(jié)點(diǎn),而現(xiàn)有的時(shí)間同步技術(shù)所能保證的誤差(10~500ms)過(guò)大,所以用時(shí)間戳來(lái)判斷狀態(tài)新舊極其不可靠。人工恢復(fù)腦裂的代價(jià)往往是“部分?jǐn)?shù)據(jù)丟失”和“更長(zhǎng)的故障恢復(fù)時(shí)長(zhǎng)”。

那么,如何防止腦裂呢?

在我看來(lái),關(guān)鍵是確保故障后能夠恢復(fù)最終一致。其前提則是,系統(tǒng)需要具備足夠的信息,以判斷出最新的狀態(tài)。然后才能將所有副本的狀態(tài)都恢復(fù)至這一狀態(tài)。在系統(tǒng)故障時(shí),即使為了保證可用性,也不應(yīng)該違反更新操作的一致性約束。

這里,“更新操作的一致性約束”指的是,系統(tǒng)為了保證一致性,而對(duì)狀態(tài)更新操作施加的約束條件。比如,最簡(jiǎn)單的主從模式下,只能通過(guò)主副本更新狀態(tài),無(wú)論任何原因無(wú)法更新主副本,那就要讓本次更新失敗,犧牲更新操作的可用性。

Paxos等一致性協(xié)議,采用了多數(shù)派(Quorum)機(jī)制保證更新操作的一致性。簡(jiǎn)單地說(shuō),就是每次更新操作必須在超過(guò)半數(shù)的副本上達(dá)成一致才算更新成功,如果在系統(tǒng)故障時(shí),更新請(qǐng)求不能達(dá)成多數(shù)派一致,也必須讓本次更新失敗。

接下來(lái),我們討論單調(diào)讀寫。

最終一致系統(tǒng)在故障時(shí),為了保證系統(tǒng)持續(xù)可用,應(yīng)允許客戶端從任意一個(gè)尚可訪問(wèn)的節(jié)點(diǎn)上讀取狀態(tài)數(shù)據(jù)。盡管這個(gè)時(shí)候,客戶端讀到的可能并非最新狀態(tài)。對(duì)于絕大多數(shù)系統(tǒng)來(lái)說(shuō),短時(shí)間內(nèi)讀到一個(gè)并非最新狀態(tài)都是可接受的。

先來(lái)看第一個(gè)例子。小明用手機(jī)銀行給小華轉(zhuǎn)了100元,當(dāng)小明完成了轉(zhuǎn)賬操作后,實(shí)際上這筆錢已經(jīng)轉(zhuǎn)入到小華的賬戶。如果這個(gè)時(shí)候因?yàn)橄到y(tǒng)故障,小華的手機(jī)銀行上顯示尚未到賬,然后過(guò)了一段時(shí)間之后才顯示到賬,也并非是完全不可接受。

然后我們?cè)賮?lái)看第二個(gè)例子,同樣還是以小明給小華轉(zhuǎn)賬來(lái)說(shuō)明。如圖二所示,在一個(gè)只有主從二副本的最終一致性系統(tǒng)中,轉(zhuǎn)賬成功后主副本的狀態(tài)已更新,小明轉(zhuǎn)給小華的錢已到賬,小華的賬戶余額是100元。但由于同步延遲,從副本中轉(zhuǎn)賬還未到賬,小華的賬戶余額還是0元。

假設(shè)小華第一次查詢賬戶的請(qǐng)求被分配到主副本上,App顯示余額100元。小華再次查詢,這次查詢請(qǐng)求被分配到了從副本上,App顯示余額0元!剛到賬的錢沒(méi)了!

對(duì)小明來(lái)說(shuō)也可能出現(xiàn)類似的問(wèn)題,轉(zhuǎn)賬成功后再查詢賬戶,如果這個(gè)查詢請(qǐng)求被分配到了從副本上(這在配置了讀寫分離的數(shù)據(jù)庫(kù)集群上是默認(rèn)的行為),發(fā)現(xiàn)賬戶余額并沒(méi)有減少,小明以為轉(zhuǎn)賬沒(méi)成功,再次發(fā)起了轉(zhuǎn)賬,結(jié)果多轉(zhuǎn)了100元。

以上這兩種情況,對(duì)外部系統(tǒng)來(lái)說(shuō)無(wú)法判斷讀到的狀態(tài)是否準(zhǔn)確,顯然是不可接受的。

▲圖2 狀態(tài)時(shí)序錯(cuò)亂問(wèn)題

要避免這兩個(gè)問(wèn)題,就需要保證在客戶端視角的一致性。所謂單調(diào)讀寫,要求對(duì)每一個(gè)客戶端來(lái)說(shuō),每次讀到的狀態(tài)不能比上次一讀寫到的狀態(tài)更舊。簡(jiǎn)單的說(shuō)就是“不能時(shí)序錯(cuò)亂”。實(shí)現(xiàn)單調(diào)讀寫有兩種常用的方法。

第一種方法是通過(guò)保持會(huì)話(Sticky Session)的方式,讓同一個(gè)客戶端的請(qǐng)求總是由與之建立會(huì)話的那個(gè)特定的服務(wù)端節(jié)點(diǎn)(副本)處理。客戶端只與服務(wù)端一個(gè)節(jié)點(diǎn)交互,自然就不會(huì)出現(xiàn)“時(shí)序錯(cuò)亂”的問(wèn)題。

保持會(huì)話的方式實(shí)現(xiàn)比較簡(jiǎn)單,很多網(wǎng)關(guān)都內(nèi)置了保持會(huì)話的功能。如果系統(tǒng)是通過(guò)網(wǎng)關(guān)對(duì)外提供服務(wù),則可以直接使用。即使系統(tǒng)沒(méi)有使用網(wǎng)關(guān),只要在客戶端首次連接成功時(shí),返回服務(wù)端節(jié)點(diǎn)的唯一標(biāo)識(shí)(ID)或URL給客戶端,后續(xù)客戶端就可以用這個(gè)ID或URL繼續(xù)訪問(wèn)同一個(gè)服務(wù)端節(jié)點(diǎn)了。

但保持會(huì)話這種實(shí)現(xiàn)方式的問(wèn)題是,在系統(tǒng)故障時(shí)需要降級(jí)。如果客戶端連不上會(huì)話中的那個(gè)服務(wù)端節(jié)點(diǎn),只能選擇去連接其它服務(wù)端節(jié)點(diǎn)創(chuàng)建新的會(huì)話。這個(gè)會(huì)話切換的過(guò)程中,仍然存在時(shí)序錯(cuò)亂的可能性。

幸運(yùn)的是時(shí)序錯(cuò)亂只可能發(fā)生在會(huì)話切換過(guò)程中,而會(huì)話切換只在系統(tǒng)故障時(shí)才發(fā)生,發(fā)生概率很低。而且,客戶端是可以感知到會(huì)話切換,從而主動(dòng)從業(yè)務(wù)邏輯上做一些補(bǔ)償。此外,因?yàn)樾枰S持會(huì)話,無(wú)法使用負(fù)載均衡策略,系統(tǒng)的彈性(Elasticity)將受到很大的限制,容易出現(xiàn)熱點(diǎn)問(wèn)題,并且擴(kuò)縮容也會(huì)受到會(huì)話的限制。

另一種方法是,通過(guò)記錄和比較狀態(tài)的版本號(hào)來(lái)實(shí)現(xiàn)單調(diào)讀寫。

系統(tǒng)需要為狀態(tài)數(shù)據(jù)維護(hù)一個(gè)版本號(hào)系統(tǒng),狀態(tài)版本號(hào)是狀態(tài)的一部分,并且要確保每次狀態(tài)更新,對(duì)應(yīng)版本號(hào)都單調(diào)遞增。這個(gè)狀態(tài)版本號(hào)的目的是,標(biāo)記狀態(tài)更新的先后順序,在英文中也稱為Ephoc或者Logical timestamps。

客戶端需要記錄上一次讀寫狀態(tài)的版本號(hào),然后在每一次讀取狀態(tài)之前比對(duì)本次版本號(hào)和上次版本號(hào),如果本次版本號(hào)不小于上次版本號(hào),就可以認(rèn)為本次讀取的狀態(tài)是可信的。否則,需要丟棄本次讀取結(jié)果,等待一會(huì)兒或者連接其它服務(wù)端重試,以獲取新版本的狀態(tài)數(shù)據(jù)。通過(guò)狀態(tài)版本號(hào)的方式實(shí)現(xiàn)單調(diào)讀寫,可以完美地保證客戶端視角的一致性,但服務(wù)端的實(shí)現(xiàn)則更加復(fù)雜。

04 小結(jié)

我們來(lái)回顧下核心內(nèi)容。

在分布式系統(tǒng)中,平衡可用性和一致性是一個(gè)難題,因此在設(shè)計(jì)過(guò)程中,需要避免未經(jīng)仔細(xì)思考而隨意增加副本的行為。

我們推薦設(shè)計(jì)者在設(shè)計(jì)系統(tǒng)一致性時(shí)能夠兼容最終一致,這樣可以極大提升系統(tǒng)在面臨故障時(shí)保持高可用的難度,在一致性和可用性上取得相對(duì)較好的平衡。但系統(tǒng)最終一致也不等于不一致,需要防止系統(tǒng)出現(xiàn)腦裂,并通過(guò)單調(diào)讀寫保證客戶端視角的一致性。

關(guān)于作者:李玥,美團(tuán)基礎(chǔ)技術(shù)部高級(jí)技術(shù)專家,極客時(shí)間《后端存儲(chǔ)實(shí)戰(zhàn)課》《消息隊(duì)列高手課》等專欄作者。曾在浪潮集團(tuán)、當(dāng)當(dāng)網(wǎng)、京東零售等公司任職。從事互聯(lián)網(wǎng)電商行業(yè)基礎(chǔ)架構(gòu)領(lǐng)域的架構(gòu)設(shè)計(jì)和研發(fā)工作多年,曾多次參與雙十一和618電商大促。專注于分布式存儲(chǔ)、云原生架構(gòu)下的服務(wù)治理、分布式消息和實(shí)時(shí)計(jì)算等技術(shù)領(lǐng)域,致力于推進(jìn)基礎(chǔ)架構(gòu)技術(shù)的創(chuàng)新與開源。


責(zé)任編輯:武曉燕 來(lái)源: 大數(shù)據(jù)DT
相關(guān)推薦

2018-03-19 09:50:50

分布式存儲(chǔ)系統(tǒng)

2017-07-25 14:38:56

數(shù)據(jù)庫(kù)一致性非鎖定讀一致性鎖定讀

2024-08-13 15:42:19

2022-12-14 08:23:30

2022-10-19 12:22:53

并發(fā)扣款一致性

2021-02-04 06:30:26

Python編程語(yǔ)言

2021-02-05 08:00:48

哈希算法?機(jī)器

2021-02-02 12:40:50

哈希算法數(shù)據(jù)

2022-02-17 21:04:27

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

2023-05-26 07:34:50

RedisMySQL緩存

2025-03-27 08:20:54

2020-08-05 08:46:10

NFS網(wǎng)絡(luò)文件系統(tǒng)

2022-09-15 10:37:46

MySQLRedis數(shù)據(jù)一致性

2019-08-30 12:46:10

并發(fā)扣款查詢SQL

2021-12-14 07:15:57

MySQLRedis數(shù)據(jù)

2023-06-25 09:44:00

一致性哈希數(shù)據(jù)庫(kù)

2021-09-30 09:20:30

分布式系統(tǒng)數(shù)據(jù)庫(kù)數(shù)據(jù)存儲(chǔ)

2017-09-21 10:59:36

分布式系統(tǒng)線性一致性測(cè)試

2011-07-25 17:38:32

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

2020-05-12 10:43:22

Redis緩存數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)