這篇文章主要講解了“保證服務(wù)器分布式系統(tǒng)數(shù)據(jù)一致性的方法有哪些”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“保證服務(wù)器分布式系統(tǒng)數(shù)據(jù)一致性的方法有哪些”吧!
創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站建設(shè)、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的開原網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
問題的起源
在電商等業(yè)務(wù)中,系統(tǒng)一般由多個獨(dú)立的服務(wù)組成,如何解決分布式調(diào)用時候數(shù)據(jù)的一致性?
具體業(yè)務(wù)場景如下,比如一個業(yè)務(wù)操作,如果同時調(diào)用服務(wù) A、B、C,需要滿足要么同時成功;要么同時失敗。A、B、C 可能是多個不同部門開發(fā)、部署在不同服務(wù)器上的遠(yuǎn)程服務(wù)。
在分布式系統(tǒng)來說,如果不想犧牲一致性,CAP 理論告訴我們只能放棄可用性,這顯然不能接受。為了便于討論問題,先簡單介紹下數(shù)據(jù)一致性的基礎(chǔ)理論。
強(qiáng)一致
當(dāng)更新操作完成之后,任何多個后續(xù)進(jìn)程或者線程的訪問都會返回最新的更新過的值。這種是對用戶最友好的,就是用戶上一次寫什么,下一次就保證能讀到什么。根據(jù) CAP 理論,這種實現(xiàn)需要犧牲可用性。
弱一致性
系統(tǒng)并不保證續(xù)進(jìn)程或者線程的訪問都會返回最新的更新過的值。系統(tǒng)在數(shù)據(jù)寫入成功之后,不承諾立即可以讀到最新寫入的值,也不會具體的承諾多久之后可以讀到。
最終一致性
弱一致性的特定形式。系統(tǒng)保證在沒有后續(xù)更新的前提下,系統(tǒng)最終返回上一次更新操作的值。在沒有故障發(fā)生的前提下,不一致窗口的時間主要受通信延遲,系統(tǒng)負(fù)載和復(fù)制副本的個數(shù)影響。DNS 是一個典型的最終一致性系統(tǒng)。
在工程實踐上,為了保障系統(tǒng)的可用性,互聯(lián)網(wǎng)系統(tǒng)大多將強(qiáng)一致性需求轉(zhuǎn)換成最終一致性的需求,并通過系統(tǒng)執(zhí)行冪等性的保證,保證數(shù)據(jù)的最終一致性。但在電商等場景中,對于數(shù)據(jù)一致性的解決方法和常見的互聯(lián)網(wǎng)系統(tǒng)(如 MySQL 主從同步)又有一定區(qū)別,群友的討論分成以下 6 種解決方案。
1. 規(guī)避分布式事務(wù)——業(yè)務(wù)整合
業(yè)務(wù)整合方案主要采用將接口整合到本地執(zhí)行的方法。拿問題場景來說,則可以將服務(wù) A、B、C 整合為一個服務(wù) D 給業(yè)務(wù),這個服務(wù) D 再通過轉(zhuǎn)換為本地事務(wù)的方式,比如服務(wù) D 包含本地服務(wù)和服務(wù) E,而服務(wù) E 是本地服務(wù) A ~ C 的整合。
優(yōu)點(diǎn):解決(規(guī)避)了分布式事務(wù)。
缺點(diǎn):顯而易見,把本來規(guī)劃拆分好的業(yè)務(wù),又耦合到了一起,業(yè)務(wù)職責(zé)不清晰,不利于維護(hù)。
由于這個方法存在明顯缺點(diǎn),通常不建議使用。
2. 經(jīng)典方案 - eBay 模式
此方案的核心是將需要分布式處理的任務(wù)通過消息日志的方式來異步執(zhí)行。消息日志可以存儲到本地文本、數(shù)據(jù)庫或消息隊列,再通過業(yè)務(wù)規(guī)則自動或人工發(fā)起重試。人工重試更多的是應(yīng)用于支付場景,通過對賬系統(tǒng)對事后問題的處理。
消息日志方案的核心是保證服務(wù)接口的冪等性。
考慮到網(wǎng)絡(luò)通訊失敗、數(shù)據(jù)丟包等原因,如果接口不能保證冪等性,數(shù)據(jù)的唯一性將很難保證。
eBay 方式的主要思路如下。
Base:一種 Acid 的替代方案
此方案是 eBay 的架構(gòu)師 Dan Pritchett 在 2008 年發(fā)表給 ACM 的文章,是一篇解釋 BASE 原則,或者說最終一致性的經(jīng)典文章。文中討論了 BASE 與 ACID 原則在保證數(shù)據(jù)一致性的基本差異。
如果 ACID 為分區(qū)的數(shù)據(jù)庫提供一致性的選擇,那么如何實現(xiàn)可用性呢?答案是
BASE (basically available, soft state, eventually consistent)
BASE 的可用性是通過支持局部故障而不是系統(tǒng)全局故障來實現(xiàn)的。下面是一個簡單的例子:如果將用戶分區(qū)在 5 個數(shù)據(jù)庫服務(wù)器上,BASE 設(shè)計鼓勵類似的處理方式,一個用戶數(shù)據(jù)庫的故障只影響這臺特定主機(jī)那 20% 的用戶。這里不涉及任何魔法,不過它確實可以帶來更高的可感知的系統(tǒng)可用性。
文章中描述了一個最常見的場景,如果產(chǎn)生了一筆交易,需要在交易表增加記錄,同時還要修改用戶表的金額。這兩個表屬于不同的遠(yuǎn)程服務(wù),所以就涉及到分布式事務(wù)一致性的問題。
文中提出了一個經(jīng)典的解決方法,將主要修改操作以及更新用戶表的消息放在一個本地事務(wù)來完成。同時為了避免重復(fù)消費(fèi)用戶表消息帶來的問題,達(dá)到多次重試的冪等性,增加一個更新記錄表 updates_applied 來記錄已經(jīng)處理過的消息。
系統(tǒng)的執(zhí)行偽代碼如下
基于以上方法,在第一階段,通過本地的數(shù)據(jù)庫的事務(wù)保障,增加了 transaction 表及消息隊列 。
在第二階段,分別讀出消息隊列(但不刪除),通過判斷更新記錄表 updates_applied 來檢測相關(guān)記錄是否被執(zhí)行,未被執(zhí)行的記錄會修改 user 表,然后增加一條操作記錄到 updates_applied,事務(wù)執(zhí)行成功之后再刪除隊列。
通過以上方法,達(dá)到了分布式系統(tǒng)的最終一致性。進(jìn)一步了解 eBay 的方案可以參考文末鏈接。
3. 去哪兒網(wǎng)分布式事務(wù)方案
隨著業(yè)務(wù)規(guī)模不斷地擴(kuò)大,電商網(wǎng)站一般都要面臨拆分之路。就是將原來一個單體應(yīng)用拆分成多個不同職責(zé)的子系統(tǒng)。比如以前可能將面向用戶、客戶和運(yùn)營的功能都放在一個系統(tǒng)里,現(xiàn)在拆分為訂單中心、代理商管理、運(yùn)營系統(tǒng)、報價中心、庫存管理等多個子系統(tǒng)。
拆分首先要面臨的是什么呢?
最開始的單體應(yīng)用所有功能都在一起,存儲也在一起。比如運(yùn)營要取消某個訂單,那直接去更新訂單表狀態(tài),然后更新庫存表就 ok 了。因為是單體應(yīng)用,庫在一起,這些都可以在一個事務(wù)里,由關(guān)系數(shù)據(jù)庫來保證一致性。
但拆分之后就不同了,不同的子系統(tǒng)都有自己的存儲。比如訂單中心就只管理自己的訂單庫,而庫存管理也有自己的庫。那么運(yùn)營系統(tǒng)取消訂單的時候就是通過接口調(diào)用等方式來調(diào)用訂單中心和庫存管理的服務(wù)了,而不是直接去操作庫。這就涉及一個『分布式事務(wù)』的問題。
分布式事務(wù)有兩種解決方式
1. 優(yōu)先使用異步消息。
上文已經(jīng)說過,使用異步消息 Consumer 端需要實現(xiàn)冪等。
冪等有兩種方式,一種方式是業(yè)務(wù)邏輯保證冪等。比如接到支付成功的消息訂單狀態(tài)變成支付完成,如果當(dāng)前狀態(tài)是支付完成,則再收到一個支付成功的消息則說明消息重復(fù)了,直接作為消息成功處理。
另外一種方式如果業(yè)務(wù)邏輯無法保證冪等,則要增加一個去重表或者類似的實現(xiàn)。對于 producer 端在業(yè)務(wù)數(shù)據(jù)庫的同實例上放一個消息庫,發(fā)消息和業(yè)務(wù)操作在同一個本地事務(wù)里。發(fā)消息的時候消息并不立即發(fā)出,而是向消息庫插入一條消息記錄,然后在事務(wù)提交的時候再異步將消息發(fā)出,發(fā)送消息如果成功則將消息庫里的消息刪除,如果遇到消息隊列服務(wù)異?;蚓W(wǎng)絡(luò)問題,消息沒有成功發(fā)出那么消息就留在這里了,會有另外一個服務(wù)不斷地將這些消息掃出重新發(fā)送。
2. 有的業(yè)務(wù)不適合異步消息的方式,事務(wù)的各個參與方都需要同步的得到結(jié)果。這種情況的實現(xiàn)方式其實和上面類似,每個參與方的本地業(yè)務(wù)庫的同實例上面放一個事務(wù)記錄庫。
比如 A 同步調(diào)用 B,C。A 本地事務(wù)成功的時候更新本地事務(wù)記錄狀態(tài),B 和 C 同樣。如果有一次 A 調(diào)用 B 失敗了,這個失敗可能是 B 真的失敗了,也可能是調(diào)用超時,實際 B 成功。則由一個中心服務(wù)對比三方的事務(wù)記錄表,做一個最終決定。假設(shè)現(xiàn)在三方的事務(wù)記錄是 A 成功,B 失敗,C 成功。那么最終決定有兩種方式,根據(jù)具體場景:
重試 B,直到 B 成功,事務(wù)記錄表里記錄了各項調(diào)用參數(shù)等信息;
執(zhí)行 A 和 B 的補(bǔ)償操作(一種可行的補(bǔ)償方式是回滾)。
對 b 場景做一個特殊說明:比如 B 是扣庫存服務(wù),在第一次調(diào)用的時候因為某種原因失敗了,但是重試的時候庫存已經(jīng)變?yōu)?0,無法重試成功,這個時候只有回滾 A 和 C 了。
那么可能有人覺得在業(yè)務(wù)庫的同實例里放消息庫或事務(wù)記錄庫,會對業(yè)務(wù)侵入,業(yè)務(wù)還要關(guān)心這個庫,是否一個合理的設(shè)計?
實際上可以依靠運(yùn)維的手段來簡化開發(fā)的侵入,我們的方法是讓 DBA 在公司所有 MySQL 實例上預(yù)初始化這個庫,通過框架層(消息的客戶端或事務(wù) RPC 框架)透明的在背后操作這個庫,業(yè)務(wù)開發(fā)人員只需要關(guān)心自己的業(yè)務(wù)邏輯,不需要直接訪問這個庫。
總結(jié)起來,其實兩種方式的根本原理是類似的,也就是將分布式事務(wù)轉(zhuǎn)換為多個本地事務(wù),然后依靠重試等方式達(dá)到最終一致性。
4. 蘑菇街交易創(chuàng)建過程中的分布式一致性方案
交易創(chuàng)建的一般性流程
我們把交易創(chuàng)建流程抽象出一系列可擴(kuò)展的功能點(diǎn),每個功能點(diǎn)都可以有多個實現(xiàn)(具體的實現(xiàn)之間有組合/互斥關(guān)系)。把各個功能點(diǎn)按照一定流程串起來,就完成了交易創(chuàng)建的過程。
面臨的問題
每個功能點(diǎn)的實現(xiàn)都可能會依賴外部服務(wù)。那么如何保證各個服務(wù)之間的數(shù)據(jù)是一致的呢?比如鎖定優(yōu)惠券服務(wù)調(diào)用超時了,不能確定到底有沒有鎖券成功,該如何處理?再比如鎖券成功了,但是扣減庫存失敗了,該如何處理?
方案選型
服務(wù)依賴過多,會帶來管理復(fù)雜性增加和穩(wěn)定性風(fēng)險增大的問題。試想如果我們強(qiáng)依賴 10 個服務(wù),9 個都執(zhí)行成功了,最后一個執(zhí)行失敗了,那么是不是前面 9 個都要回滾掉?這個成本還是非常高的。
所以在拆分大的流程為多個小的本地事務(wù)的前提下,對于非實時、非強(qiáng)一致性的關(guān)聯(lián)業(yè)務(wù)寫入,在本地事務(wù)執(zhí)行成功后,我們選擇發(fā)消息通知、關(guān)聯(lián)事務(wù)異步化執(zhí)行的方案。
消息通知往往不能保證 100% 成功;且消息通知后,接收方業(yè)務(wù)是否能執(zhí)行成功還是未知數(shù)。前者問題可以通過重試解決;后者可以選用事務(wù)消息來保證。
但是事務(wù)消息框架本身會給業(yè)務(wù)代碼帶來侵入性和復(fù)雜性,所以我們選擇基于 DB 事件變化通知到 MQ 的方式做系統(tǒng)間解耦,通過訂閱方消費(fèi) MQ 消息時的 ACK 機(jī)制,保證消息一定消費(fèi)成功,達(dá)到最終一致性。由于消息可能會被重發(fā),消息訂閱方業(yè)務(wù)邏輯處理要做好冪等保證。
所以目前只剩下需要實時同步做、有強(qiáng)一致性要求的業(yè)務(wù)場景了。在交易創(chuàng)建過程中,鎖券和扣減庫存是這樣的兩個典型場景。
要保證多個系統(tǒng)間數(shù)據(jù)一致,乍一看,必須要引入分布式事務(wù)框架才能解決。但引入非常重的類似二階段提交分布式事務(wù)框架會帶來復(fù)雜性的急劇上升;在電商領(lǐng)域,絕對的強(qiáng)一致是過于理想化的,我們可以選擇準(zhǔn)實時的最終一致性。
我們在交易創(chuàng)建流程中,首先創(chuàng)建一個不可見訂單,然后在同步調(diào)用鎖券和扣減庫存時,針對調(diào)用異常(失敗或者超時),發(fā)出廢單消息到MQ。如果消息發(fā)送失敗,本地會做時間階梯式的異步重試;優(yōu)惠券系統(tǒng)和庫存系統(tǒng)收到消息后,會進(jìn)行判斷是否需要做業(yè)務(wù)回滾,這樣就準(zhǔn)實時地保證了多個本地事務(wù)的最終一致性。
5. 支付寶及螞蟻金融云的分布式服務(wù) DTS 方案
業(yè)界常用的還有支付寶的一種 xts 方案,由支付寶在 2PC 的基礎(chǔ)上改進(jìn)而來。主要思路如下,大部分信息引用自官方網(wǎng)站。
分布式事務(wù)服務(wù)簡介
分布式事務(wù)服務(wù) (Distributed Transaction Service, DTS) 是一個分布式事務(wù)框架,用來保障在大規(guī)模分布式環(huán)境下事務(wù)的最終一致性。DTS 從架構(gòu)上分為 xts-client 和 xts-server 兩部分,前者是一個嵌入客戶端應(yīng)用的 JAR 包,主要負(fù)責(zé)事務(wù)數(shù)據(jù)的寫入和處理;后者是一個獨(dú)立的系統(tǒng),主要負(fù)責(zé)異常事務(wù)的恢復(fù)。
核心特性
傳統(tǒng)關(guān)系型數(shù)據(jù)庫的事務(wù)模型必須遵守 ACID 原則。在單數(shù)據(jù)庫模式下,ACID 模型能有效保障數(shù)據(jù)的完整性,但是在大規(guī)模分布式環(huán)境下,一個業(yè)務(wù)往往會跨越多個數(shù)據(jù)庫,如何保證這多個數(shù)據(jù)庫之間的數(shù)據(jù)一致性,需要其他行之有效的策略。在 JavaEE 規(guī)范中使用 2PC (2 Phase Commit, 兩階段提交) 來處理跨 DB 環(huán)境下的事務(wù)問題,但是 2PC 是反可伸縮模式,也就是說,在事務(wù)處理過程中,參與者需要一直持有資源直到整個分布式事務(wù)結(jié)束。這樣,當(dāng)業(yè)務(wù)規(guī)模達(dá)到千萬級以上時,2PC 的局限性就越來越明顯,系統(tǒng)可伸縮性會變得很差?;诖耍覀儾捎?BASE 的思想實現(xiàn)了一套類似 2PC 的分布式事務(wù)方案,這就是 DTS。DTS在充分保障分布式環(huán)境下高可用性、高可靠性的同時兼顧數(shù)據(jù)一致性的要求,其最大的特點(diǎn)是保證數(shù)據(jù)最終一致 (Eventually consistent)。
簡單的說,DTS 框架有如下特性:
最終一致:事務(wù)處理過程中,會有短暫不一致的情況,但通過恢復(fù)系統(tǒng),可以讓事務(wù)的數(shù)據(jù)達(dá)到最終一致的目標(biāo)。
協(xié)議簡單:DTS 定義了類似 2PC 的標(biāo)準(zhǔn)兩階段接口,業(yè)務(wù)系統(tǒng)只需要實現(xiàn)對應(yīng)的接口就可以使用 DTS 的事務(wù)功能。
與 RPC 服務(wù)協(xié)議無關(guān):在 SOA 架構(gòu)下,一個或多個 DB 操作往往被包裝成一個一個的 Service,Service 與 Service 之間通過 RPC 協(xié)議通信。DTS 框架構(gòu)建在 SOA 架構(gòu)上,與底層協(xié)議無關(guān)。
與底層事務(wù)實現(xiàn)無關(guān): DTS 是一個抽象的基于 Service 層的概念,與底層事務(wù)實現(xiàn)無關(guān),也就是說在 DTS 的范圍內(nèi),無論是關(guān)系型數(shù)據(jù)庫 MySQL,Oracle,還是 KV 存儲 MemCache,或者列存數(shù)據(jù)庫 HBase,只要將對其的操作包裝成 DTS 的參與者,就可以接入到 DTS 事務(wù)范圍內(nèi)。
以下是分布式事務(wù)框架的流程圖
實現(xiàn)
一個完整的業(yè)務(wù)活動由一個主業(yè)務(wù)服務(wù)與若干從業(yè)務(wù)服務(wù)組成。
主業(yè)務(wù)服務(wù)負(fù)責(zé)發(fā)起并完成整個業(yè)務(wù)活動。
從業(yè)務(wù)服務(wù)提供 TCC 型業(yè)務(wù)操作。
業(yè)務(wù)活動管理器控制業(yè)務(wù)活動的一致性,它登記業(yè)務(wù)活動中的操作,并在活動提交時確認(rèn)所有的兩階段事務(wù)的 confirm 操作,在業(yè)務(wù)活動取消時調(diào)用所有兩階段事務(wù)的 cancel 操作?!?/p>
與 2PC 協(xié)議比較
沒有單獨(dú)的 Prepare 階段,降低協(xié)議成本
系統(tǒng)故障容忍度高,恢復(fù)簡單
6. 農(nóng)信網(wǎng)數(shù)據(jù)一致性方案
1. 電商業(yè)務(wù)
公司的支付部門,通過接入其它第三方支付系統(tǒng)來提供支付服務(wù)給業(yè)務(wù)部門,支付服務(wù)是一個基于 Dubbo 的 RPC 服務(wù)。
對于業(yè)務(wù)部門來說,電商部門的訂單支付,需要調(diào)用
支付平臺的支付接口來處理訂單;
同時需要調(diào)用積分中心的接口,按照業(yè)務(wù)規(guī)則,給用戶增加積分。
從業(yè)務(wù)規(guī)則上需要同時保證業(yè)務(wù)數(shù)據(jù)的實時性和一致性,也就是支付成功必須加積分。
我們采用的方式是同步調(diào)用,首先處理本地事務(wù)業(yè)務(wù)。考慮到積分業(yè)務(wù)比較單一且業(yè)務(wù)影響低于支付,由積分平臺提供增加與回撤接口。
具體的流程是先調(diào)用積分平臺增加用戶積分,再調(diào)用支付平臺進(jìn)行支付處理,如果處理失敗,catch 方法調(diào)用積分平臺的回撤方法,將本次處理的積分訂單回撤。
(點(diǎn)擊圖片可以全屏縮放)
2. 用戶信息變更
公司的用戶信息,統(tǒng)一由用戶中心維護(hù),而用戶信息的變更需要同步給各業(yè)務(wù)子系統(tǒng),業(yè)務(wù)子系統(tǒng)再根據(jù)變更內(nèi)容,處理各自業(yè)務(wù)。用戶中心作為 MQ 的 producer,添加通知給 MQ。APP Server 訂閱該消息,同步本地數(shù)據(jù)信息,再處理相關(guān)業(yè)務(wù)比如 APP 退出下線等。
我們采用異步消息通知機(jī)制,目前主要使用 ActiveMQ,基于 Virtual Topic 的訂閱方式,保證單個業(yè)務(wù)集群訂閱的單次消費(fèi)。
感謝各位的閱讀,以上就是“保證服務(wù)器分布式系統(tǒng)數(shù)據(jù)一致性的方法有哪些”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對保證服務(wù)器分布式系統(tǒng)數(shù)據(jù)一致性的方法有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!
本文名稱:保證服務(wù)器分布式系統(tǒng)數(shù)據(jù)一致性的方法有哪些
文章網(wǎng)址:http://www.rwnh.cn/article46/jehdeg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、、手機(jī)網(wǎng)站建設(shè)、小程序開發(fā)、外貿(mào)建站、全網(wǎng)營銷推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)