分布式业务的异常解决思路
傳統(tǒng)意義上的事務被定義在數(shù)據(jù)層面,它是指一組原子操作,這組原子操作必須按照既定的順序全部執(zhí)行成功 。 如果某一個或者多個原子操作失敗,則回退所有之前的原子操作到原來的狀態(tài) 。
事務的特點主要有四個:原子性( Atomicity )、 一致性( Consistency )、隔離性( Isolation )和持久性( Durability )。
一個標準的事務必須同時滿足這四個特性,否則就無法保持業(yè)務數(shù)據(jù)的正確性一一并且在 SQL 規(guī)范中也明確定義了這些特性的實現(xiàn)標準,例如它定義了四類事務隔離級別: Read Uncommitted (讀未提交〉、 Read Committed (讀己提交)、 Repeatable Read(可重復讀 )和 Serializable ( 可串行化〉 。
傳統(tǒng)業(yè)務環(huán)境下這些原子數(shù)據(jù)操作都在同一個數(shù)據(jù)庫實例上完成 , 而隨著企業(yè)中各系統(tǒng)的復雜度增加,就可能會出現(xiàn)事務跨兩個或者多個系統(tǒng)數(shù)據(jù)庫實例的情況 , 后一種事務處理機制就是常說的分布式事務。
1.分布式事務與兩階段提交協(xié)議(2PC)--作用于系統(tǒng)數(shù)據(jù)層
兩階段提交協(xié)議( 2PC ) 。 簡單來說這個協(xié)議中提到兩個階段是指準備階段和提交階段
它的實現(xiàn)一般需要一個事務協(xié)調(diào)者來統(tǒng)一所有工作,協(xié)調(diào)者首先向參與事務動作的各個數(shù)據(jù)節(jié)點提交準備請求(也叫檢查請求),并等待所有參與此事務的數(shù)據(jù)節(jié)點返回確認信息。當各個數(shù)據(jù)節(jié)點收到這個準備請求后就會檢查自己是否有條件執(zhí)行自己負責的處理部分,并且執(zhí)行但不提交各自負責的這部分數(shù)據(jù)操作。這是一個同步過程,在收到所有節(jié)點確認信息之前協(xié)調(diào)者都不會發(fā)出下一步的執(zhí)行指令, 各個節(jié)點被鎖定/預占的資源也不會被釋放一一因為各數(shù)據(jù)節(jié)點的處理過程都未正式提交。如果在這個過程中任何一個數(shù)據(jù)節(jié)點返回了“不可用”或者等待超時,那么協(xié)調(diào)者就會向各個參與事務動作的處理節(jié)點發(fā)出“回液”指令,各個處理節(jié)點就會 回滾/釋放資源,并將回滾結果回饋給協(xié)調(diào)者 ;如果協(xié)調(diào)者收到所有處理節(jié)點“準備好”/“同意”的信號,那么就會進入第二個階段一一通知各個處理節(jié)點“提交” 。當各個處理節(jié)點收到第二步指令后,就會正式提交上一步已經(jīng)完成的處理動作,并向協(xié)調(diào)者回饋“完成”消息 。
分布式事務己經(jīng)有非常多的實現(xiàn)組件和成功案例,例如第三方組件:
> JOTM (Java Open Transaction Manager)就是一個成熟的分布式事務管理器,現(xiàn)在許多 Tomcat 服務器上都是用它提供的分布式事務功能:
> Atomikos 也是一款常用的分布式事務管理器,也是目前配合Spring 集成的一款分布式事務管理器 。
2.關系型數(shù)據(jù)庫的設計的 ACID 原理
即原子性( Atomicity )、 一致性( Consistency )、隔離性( Isolation )和持久性( Durability ),而且關系型數(shù)據(jù)庫普遍采用事務技術實現(xiàn) ACID原理,其中每一個事務就是最小的原子操作,還可以設置不同的事務級別,包括可讀未提交、可重復讀這樣的事務級別:關系型數(shù)據(jù)庫還規(guī)定了 一旦事務正確提交就不能進行數(shù)據(jù)回滾 , 如果要繼續(xù)修改數(shù)據(jù)就只能啟動一個新的事務 。 而這一切都是為了保證數(shù)據(jù)庫系統(tǒng)是一個強一致性系統(tǒng)。 就連架設在各個關系型數(shù)據(jù)庫實例之上的分布式事務機制,也是為了保證這個 目標。
只要有任何一個參與分布式事務過程的數(shù)據(jù)庫實例出現(xiàn)異常,整個分布式事務就無法正常提交 ,當然也就無法完成數(shù)據(jù)寫操作 。 注意,數(shù)據(jù)是可以在事務操作的同時進行讀操作的,即使某些節(jié)點出現(xiàn)了 問題其他數(shù)據(jù)庫節(jié)點也可以承擔這個讀操作 , 因為這樣的操作不存在一致性改變的風險。
3.TCC (Try Commit Cancel)--作用于系統(tǒng)RPC層
TCC 過程實際上是 2PC 的一種變形,它與后者的關鍵區(qū)別在于 TCC 的思路著重于原子服務而非具體數(shù)據(jù)操作。 Try步驟的細分工作又包括業(yè)務檢查和資源預占,而對于如何實現(xiàn)這個過程,在 TCC 中并沒有明確要求必須通過對持久層數(shù)據(jù)進行寫操作,這就便于架構師在服務層而非在數(shù)據(jù)層上設計 TCC 的實現(xiàn)。
4.CAP
分布式系統(tǒng)的知識體系中有一個非常重要的概念一一CAP 原理。這個原理指導著大多數(shù)分布式系統(tǒng)的設計過程 ,
CAP 原理大致是說分布式系統(tǒng)中一定存在三個特性 : 一 致性( Consistency )、分區(qū)容忍性( Partition )和可用性( Availability ) 。
HBase選擇了C(一致性)與P(分區(qū)可容忍性),Cassandra選擇了A(可用性)與P(分區(qū)可容忍性),HDFS 選擇了P(分區(qū)可容忍性)與A(可用性)
分區(qū)性的要求:數(shù)據(jù) X 至少也應該在不同的節(jié)點上存儲多份(至少應該有三份),存儲的副本量越多越能保證數(shù)據(jù) X 的安全,也越能保證即使在多個節(jié)點同時不可用的情況下,數(shù)據(jù) X 也同樣能夠被訪問 。
一致性的要求:當客戶端發(fā)出數(shù)據(jù) X 的更新請求后, 從任何一個節(jié)點訪問數(shù)據(jù) X 都可以拿到它最新的狀態(tài)。如果真要達到這么理論的一致性要求,那就只能讓所有需要讀/寫數(shù)據(jù) X的客戶端等待 , 直到完成數(shù)據(jù) X 的所有副本同步后,再依次進行響應 。 但這樣做又不滿足可用性要求。
可用性的要求:任何一個沒有發(fā)生故障的節(jié)點必須在有限的時間內(nèi)返回結果。然而,如果系統(tǒng)能夠做到當某個節(jié)點發(fā)生網(wǎng)絡分區(qū)后,將它從系統(tǒng)中剔除,由其它節(jié)點繼續(xù)提供服務。雖然沒有滿足CAP中A的要求,但是,只要恢復時間足夠快,也符合高可用的要求。
5.BASE
BASE ,即 基本可用 ( Basically Availble )、軟狀態(tài)( Soft State )和最終一致( Eventual Consistency ) ,
任何分布式系統(tǒng)都不可能以 CAP 原理中三個特性同時作為設計目標,沒有任何分區(qū)容忍性的分布式系統(tǒng)甚至都不能稱為分布式系統(tǒng)。
一致性的概念:強一致性和最終一致性 。
強一致性可以概括為任何時刻客戶在分布式系統(tǒng)中獲取數(shù)據(jù) X,無論它在分布式系統(tǒng)的哪個節(jié)點進行這個操作,其獲取到的數(shù)據(jù) X 都是一致的 。 從這個定義來看 ,分布式事務機制就是一種強一致性的實現(xiàn) 。
弱一致性不是說不保持數(shù)據(jù)的一致性,而是說不保證數(shù)據(jù)每時每刻都一致,也不承諾什么 時候才能保證分布式系統(tǒng)的任何節(jié)點都能讀取到一致的數(shù)據(jù)。而最終一致性是弱一致性的一種特定結果, 即是承諾基于弱一致性,在經(jīng)過一個數(shù)據(jù)不一致的時間窗口后,最終能保證數(shù)據(jù)一致 。 這個數(shù)據(jù)不一致的時間窗口在客戶端看來非常短,而且分布式系統(tǒng)還可以通過多種方式向客戶端屏蔽不一致的數(shù)據(jù),例
如主從副本方式 。
BASE 的核心思路是在保證可用性和分區(qū)容忍性的前提下,找到一個犧牲一致性的程度,而最終一致性為我們指明了 這個程度一一保證數(shù)據(jù)最終一致即可。那么對于跨系統(tǒng)分布式業(yè)務我們也可以借鑒這個概念: 各個原子服務無須關心其他原子服務什么時候執(zhí)行或者執(zhí)行順序,只需要各自負責自己的那部分業(yè)務,并最終完成處理即可。如果出現(xiàn)需要回退的情況,則各個原子服務負責取消自己負責的那部分操作 , 回到原始狀態(tài) 。
6.事務補償機制
這種機制本身并不提供事務,而是在需要進行回溶操作時能夠依據(jù)某種手段獲知整個執(zhí)行路徑,并完成符合業(yè)務規(guī)則的逆向執(zhí)行動作。為了保證事務補償機制能夠運行,業(yè)務系統(tǒng)提供了某個原子服務就必須提供一個和這個原子服務反向操作的另一個原子服務,這樣才可以保證事務補償機制在任何一個正 向執(zhí)行的分布式業(yè)務工作的環(huán)境中,都有一個與之對應的反向執(zhí)行過程。
當一個原子服務被執(zhí)行時數(shù)據(jù)即時被更改,占用資源使用后即時被釋放,執(zhí)行日志被詳細記錄。如果某一個原子服務執(zhí)行失敗并不是將之前未提交數(shù)據(jù)回滾,而是通過一個對應的反向服務將之前的結果逆向執(zhí)行,這里的逆向執(zhí)行將重新修改數(shù)據(jù) 、 重新占用資源、重新生成新的日志。根據(jù)各個原子服務間的依賴性,這個執(zhí)行過程既可以是順序執(zhí)行的又可以是并行執(zhí)行的。
事務補償機制可以通過多種方式進行實現(xiàn):
1.獨立實現(xiàn)一個事務補償控制模塊,井向這個模塊注冊每一個正向方法和對應的逆向方法,跨系統(tǒng)業(yè)務由這個模塊負責執(zhí)行井在出現(xiàn)執(zhí)行錯誤的情況下進行重試或者逆向執(zhí)行:
2.采用日志方式進行實現(xiàn),將跨系統(tǒng)業(yè)務的發(fā)起方和各個執(zhí)行方執(zhí)行的每一步寫入日志,并在出現(xiàn)執(zhí)行錯誤時利用日志記錄的信息分析和執(zhí)行回滾策略,最后還要通過日志記錄整個業(yè)務是否達到了最終一致性。
應用場景:
事務補償機制可以解決長耗時業(yè)務過程中資源占用的問題,但是還是不能有效縮短業(yè)務執(zhí)行時間 。因為在每個原子服務執(zhí)行完成后資源就被釋放了,而不是像兩階段提交協(xié)議那樣在整個業(yè)務執(zhí)行完成前都需要獨占資源。
事務補償機制雖然部分解決了分布式事務在業(yè)務系統(tǒng)的適用度問題,但是它本身也不是完美的。例如它不適用需要保證實時一致性的業(yè)務場景,
6.可靠的異步消息
可靠的異步消息系統(tǒng)是目前解決這類問題(電商訂單涉及多個子系統(tǒng)調(diào)用的問題)所常用的方式,
“可靠”的定義是消息系統(tǒng)不會無故丟失消息,保證消息送達到指定的目標系統(tǒng):
“異步”是指消息的發(fā)送方(又稱生產(chǎn)方)在迭出消息后 ,無須等待消息接收方(又稱消費方)反饋任何結果即可執(zhí)行后續(xù)的操作。
典型的可靠的異步消息系統(tǒng)有 ActiveMQ 、 RabbitMQ 和 RocketMQ。
7.為保持最終一致性的事務補償機制,或者又是可異步工作的可靠消息系統(tǒng),在設計和使用時都需要注意問題
1)注意重試操作:由于分布式業(yè)務的各個執(zhí)行步驟存在于不同的系統(tǒng)中,這些系統(tǒng)依靠網(wǎng)絡進行互相通信,所以在服務的調(diào)用過程中不可能保證 100%成功 。 也就是說即使每個原子服務工作正常,整個分布式業(yè)務的工作過程也可能因為某些工作環(huán)境原因而調(diào)用失敗,所以一旦某個原子服務調(diào)用失敗,協(xié)調(diào)者要做的事情并不是立即進行業(yè)務回滾、逆向操作或者異常消息通知,而應該首先進行重試操作,這是為了排除包括網(wǎng)絡抖動、主從服務切換在內(nèi)的服務臨時不可用情況 。經(jīng)過一定數(shù)量的重試后,如果服務還是不可用,則協(xié)調(diào)者再進行業(yè)務回液、逆向操作或者異常消息通知 。 以上示例代碼的客戶端并沒有任何的重試過程,就開始進行逆向操作了 。
2)注意冪等性:所謂冪等性是指參與同 一個分布式業(yè)務的各個操作步驟,無論執(zhí)行多少次操作動作其結果都與執(zhí)行一次操作動作后的結果一致。實際上這是對重試操作特性的一種支持,由于重試操作在異常情況下進行,所以誰也不能保證原子服務不會被錯誤地多次調(diào)用,甚至不能保證請求發(fā)起者不會錯誤地重復發(fā)起同一個分布式業(yè)務操作過程 。 例如,訂單生成時要避免重復生成的情況發(fā)生、訂單執(zhí)行過程要防止出 現(xiàn)重復生成配送單的情況、訂單逆向執(zhí)行的退款步驟要防止重復退款的情況發(fā)生。
3)注意基于日志:日志的作用可概括為事中記錄和事后回溯, 一個分布式服務過程的每一個執(zhí)行步驟都應該詳細記錄日志,無論這個過程是正向執(zhí)行還是逆向執(zhí)行; 在分布式服務執(zhí)行完成后也應該記錄日志,無論這個分布式服務執(zhí)行是否成功 。這些日志可以在分布式業(yè)務執(zhí)行結束后檢查最后的執(zhí)行效果,在協(xié)調(diào)器出現(xiàn)窯機時利用日 志恢復協(xié)調(diào)器執(zhí)行狀態(tài)保持執(zhí)行過程的一致性,在需要進行逆向執(zhí)行時也可利用日志找到對應的回溯路徑。以之前的示例代碼來說 , Invoker 角色中的代碼雖然可以在某個原子服務出現(xiàn)異常時,按照分布式業(yè)務對應的逆向過程進行執(zhí)行,但是卻沒有使用任何辦法保證逆向過程執(zhí)行的可靠性一一沒有記錄日志 。 所以要是某個原子服務執(zhí)行的逆向過程失敗,整個系統(tǒng)的數(shù)據(jù)一致性就沒有保證了。
4)參與分布式服務的各個原子服務,在沒有業(yè)務間依賴的情況下可以采用并行執(zhí)行的方式縮短整個分布式服務的執(zhí)行時間 ,提高執(zhí)行效率。
8.Hystrix與熔斷機制
通過多種手段幫助技術人員解決系統(tǒng)間調(diào)用時的錯誤,防止系統(tǒng)雪崩效應。Hystrix 將分布式業(yè)務的正向操作和逆向操作分離開,并通過設置最長等待時間、拋出異常等方式讓逆向操作自動執(zhí)行。
關鍵點
1)首先 Hystrix 的單次執(zhí)行是以一個命令完成的,其內(nèi)是一個完整的命令模式,其外向開發(fā)人員暴露的是一個命令元素(Command 角色,其實現(xiàn)為HystrixCommand<R> 類或 HystrixExecutable<R>接口)。
開發(fā)人員需要實現(xiàn)其中的 run()方法與getFallback()方法
2)Hystrix 將具體的任務(一個 Command 角色)放入線程池中執(zhí)行,而且 Hystrix 中不但可以管理 一 個線程池,還可以為不同的 Command 設置不同的ThreadPoo!Key , 讓它們工作在不同 的線程池中
3)Hystrix 對 Command 的執(zhí)行分為三種方式,同步執(zhí)行 execute()、異步執(zhí)行 queue()和帶有觀察器的執(zhí)行方式 observe()
9.系統(tǒng)間服務調(diào)用的問題
1)訪問權限問題:
在整個系統(tǒng)生態(tài)環(huán)境中,不是任何用戶都可以隨意訪問任意業(yè)務服務接口的 。 除了訪問接口的用戶組、用戶和密碼管理(或者是公私鑰文件),還需要限制用戶的訪問權限。
2)版本控制問題:
為了子系統(tǒng)能夠保證 24 小時連續(xù)提供服務,就需要標注服務接口的版本號,讓之前沒有完成升級的服務節(jié)點提供/訪問老版本的服務接口:己經(jīng)完成升級的服務節(jié)點提供新版本的服務接口。
3)服務時效、次數(shù)控制問題:
各個子系統(tǒng)提供的服務本身也是具有時效性的。比如某一個服務 Y 只在每天早上 10 : 00~11 :00 才能提供訪問調(diào)用,且對于某個用戶來說每天只能調(diào)用 100 次。
4)性能措施問題:
系統(tǒng)服務接口能夠承受多大的 TPS 是衡量其性能的一個重要指標 。 但是在生產(chǎn)環(huán)境下,往往再高的系統(tǒng)接口都會遇到 TPS 瓶頸。在此種情況下,我們一般會準備備用手段對請求進行導流,
5)跨平臺性問題:
在有歷史遺留情況的系統(tǒng)中,或者有多個技術背景不同的團隊同時進行研發(fā)的大中型業(yè)務系統(tǒng)中,這就要求遠程業(yè)務接口能夠支持多種語言客戶端的調(diào)用 。 目前對這類問題的解決方法無外乎幾種:
(1)一種是使用各開發(fā)語言都更容易理解和管理的基于網(wǎng)絡應用層協(xié)議的接口調(diào)用方式,例如 HTTP RESTful 形式的服務接口:
(2)一種是基于某種支持跨語言特性的RPC 組件提供接口支持,例如基于 Apache Thrift提供的服務接口 :
(3)還有一種是代理裝置,通過這個代理裝置,將某種語言某種消息格式的調(diào)用轉換為另 一種語言另一種消息格式的調(diào)用,而 ESB 技術就類似于這樣一種代理裝置。
10.SOA架構
SOA ( Service-Oriented Architecture ) 中文全稱 “面向服務的架構” 。 SOA 主要圍繞多個 “服務”如何進行集成以達到某種服務目的進行討論 。
服務: 在業(yè)務系統(tǒng)中被發(fā)布出來供用戶使用,并能夠完成一個完整業(yè)務過程的功能。
服務著眼于完整的業(yè)務:服務的定義對象是業(yè)務系統(tǒng)中的完整業(yè)務功能。
服務的粒度雖然相對粗放,但卻是可控的:服務拆分的目標是保留重用度:務粒度的拆分完全依據(jù)業(yè)務系統(tǒng)中業(yè)務過程進行定義和分析
服務集成的目的是形成一個新的服務:對企業(yè)內(nèi)部(或者企業(yè)間〉的業(yè)務服務進行集成,被集成的業(yè)務服務稱之為原子服務,集成的目 的是重用這些原子服務形成一個新的服務。
SOA 需保證屏蔽細節(jié):從技術細節(jié)層面看,開發(fā)語言、外傳輸協(xié)議、消息格式都可以使用 SOA 進行集成與轉換;從業(yè)務細節(jié)層面看, 第三方系統(tǒng)只需要知道調(diào)用某一個服務就可以達到業(yè)務目的,至于提供服務的業(yè)務系統(tǒng)如何實現(xiàn)業(yè)務過程則無須關心。
SOA 讓各業(yè)務系統(tǒng)保持松散:通過屏蔽各業(yè)務系統(tǒng)技術細節(jié)和業(yè)務細節(jié),兼容各業(yè)務系統(tǒng)的不同傳輸協(xié)議和不同消息格式,可以讓通過 SOA進行業(yè)務集成的,各個業(yè)務系統(tǒng)保持低禍合狀態(tài)。
11.ESB
SOA 架構模型是解決問題的綱領性思路,在這個規(guī)則下ESB ( Enterprise Service Bus ,企業(yè)服務總線〉是其一種具體辦法。
為了滿足 SOA 架構思想的設計要點,達到既定的工作目標, ESB 總錢技術至少需要幫助這些業(yè)務系統(tǒng)完成以下工作。
· 多種調(diào)用協(xié)議的兼容支撐和轉換
· 多種消息格式兼容支撐和轉換
· 服務監(jiān)控管理(注冊、安全、版本、優(yōu)先級):首先業(yè)務系統(tǒng)提供的服務可能會以-定周期發(fā)生變化,ESB能夠保證在這樣的情況下集成服務依然可以工作;其次ESB 應該有一套完整的功能來保證服務集成的安全性和權限 。
· 服務集成和編排:服務編排的作用就是明確原子服務執(zhí)行的先后順序、判斷原子服務執(zhí)行的條件、確保集成后的新服務能夠按照業(yè)務設計者的要求正常工作 。
常見的 ESB 產(chǎn)品
1.IBM 提供了兩款純軟件的 ESB 產(chǎn)品 : IBM WebSphere ESB 和 IBM WebSphere MessageBroker(WMB〉
2.Oracle Service Bus ( OSB )是 Oracle 的付費產(chǎn)品,和 WMB 類似, OSB 也是全分布式的ESB 產(chǎn)品
3.普元 ESB 產(chǎn)品是國內(nèi)比較有代表性的擁有自 主產(chǎn)權的 ESB 產(chǎn)品 。
4.Mule ESB 是服務提供商 MuleSoft的產(chǎn)品
5.Apache Camel 是 Apache 基金會下的一個頂級開源項目,它提供了一套消息路由規(guī)則、消息轉換引擎和服務編排等能力。 不過它并沒有現(xiàn)成的消息轉換組件
12.服務治理框架
ESB 企業(yè)總線的存在目的之一是滿足企業(yè)建設過程中新系統(tǒng)和遺留系統(tǒng)的集成問題,所以ESB 中的一個功能側重點就是協(xié)議轉換和信息轉發(fā)
服務治理框架并不進行原子服務的真實調(diào)用,而只記錄原子服務的調(diào)用地址、權限、熔斷方案、備用路徑等信息,井在各原子服務調(diào)用時監(jiān)控實時壓力 。當D 系統(tǒng)需要調(diào)用外圍系統(tǒng)時,首先會請求服務治理框架拿到真實的調(diào)用路徑 , 再自行進行調(diào)用。
降低了服務調(diào)用的跨平臺能力、服務編排能力和對遺留系統(tǒng)的集成能力,但是顯著提高了各系統(tǒng)間的調(diào)用吞吐量以及各系統(tǒng)集成到服務治理框架上的難度,非常適合互聯(lián)網(wǎng)系統(tǒng)對于輕量化和快速部署的要求。
常見的服務治理框架軟件
1. 阿里 DUBBO
2. Spring Cloud(Config、Eureka、Hystrix、Zuul、Ribbon等)
總結
以上是生活随笔為你收集整理的分布式业务的异常解决思路的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第三次学JAVA再学不好就吃翔(part
- 下一篇: 第三次学JAVA再学不好就吃翔(part