1,柔性事物,二階段2PC型,補償型,異步確保型,最大努力通知型。
2PC適合場景:客戶賬,收費
異步確保型:會計性,資金訂單,通知數據。
核心交易數據分庫并分表,消費記錄數據分庫分表,商戶交易數據分庫分表。
保持多個維度的數據集群可以使用MQ異步同步,MQ異步也會導致數據不一致,則引入實時監控服務,實時計算2個維度集群差異,作一致性同步。
2,事務型MQ,在本地邏輯處理前發送MQ,本地邏輯執行成功后,提交commit MQ消息,MQ失敗則重試直到成功。也可用MQ定時補償,單獨補償任務表出來,這樣顯得更為清晰。
一致性重試需要解決冪等,可以采用樂觀鎖,version號去重,樂觀鎖失敗證明版本上升了,失敗了走查version再更新,設計較多的去重的可以單獨一張表做去重服務,利用DB唯一索引特性,或采用zookeeper和redis分布式鎖lock,類似多線程并發鎖。
避免XA事務,通信時間較長資源鎖定等待久。利用異步做最終一致性方式較好,MQ如支付寶賬號扣錢之后只生成1個MQ即可,只要該消息可靠保存,依靠該消息完成最終一致性。
3,微信支付采用postgreSQL數據庫,XS在事務管理機制會成為系統瓶頸,全局事務管理器會限制系統的擴展規模,每個request進來后協調節點都會向全局事務管理器GTM申請必須的全局事務ID,全局快照信息,并把這些信息隨著SQL本身一起發往DN節點執行,只有主DN才會獲取gxid,備DN沒有自己的gxid。微信改進后不再從全局事務管理器GTM獲取gxid和全局快照信息,每個節點使用自己的本地xid和快照,備DN也可以提供只讀服務,先對分布式列計算hash,然后用這個值對集群中的節點個數取模決定哪個節點。
4,一致性補償服務,需要先要確定失敗的步驟和狀態,確定補償的范圍,再能提供補償使用的業務數據和業務流水等更多要素,當客戶1個預定請求到達時,補償協調服務為請求生成1個全局唯一的業務流水號,并在調用各個工作服務的的同時完整記錄完整的狀態,記錄調用的業務流水,記錄調用bookhotel業務流水和bookTrain流水再調用服務等,補償過程服務同樣也需要重試機制,要求本身也具有冪等性,由于業務因素失敗不需要重試而是數據庫等記錄異常手動處理,因網絡原因則需要重試,500錯誤的則等一段時間再重試。
5,dubbo分布式事務,使用異常exception拋出,A服務調用B服務,B服務調用C服務,C服務出現異常會拋給B,B異常也會拋給A,C回滾則B也回滾,B回滾則A也回滾。MQ最終一致性可以利用系統控制MQ的消息狀態如預備、發送、提交、成功、失敗、重試中等。TCC補償事務則分為try confiirm cancel三個途徑,try對業務檢測及資源預留confirm做業務提交,cancel做業務回滾,Try節點可能存在失敗則調用cancel釋放資源。 最大努力通知型多用在第三方系統通訊時,如調用微信支付后結果通知,如通過MQ發送http請求,設置最大通知數,不保證成功,提供結果查詢接口,多系統之間同步,Dubbo之間調用也可采用最大通知反饋。
6,用戶啟動1個事務,transactionManager.begin(),事務管理器在當前線程初始化1個事務實例,threadLocal.set( new TransationImpl() ),用戶調用jdbc/jms/dubbo請求,請求內部初始化1個XAResource實例,XAResource xsResource = new XAResourceImpl(); jdbc/jms/dubbo從當前線程獲取事務,transation將當前XAResource注冊到事務中,transation.enlistResource(xsResource),用戶提交1個事務:transationManager.commit()。事務for循環調用所有注冊的XAResource的2階段提交,Xid xid = new XidImpl(); for(XAResource x : xaResources){ x.prepare(ID), xa.commit(xid, true); 還有些異常流程如rollback和forget等,距離TransationManager tm = newTransationManager (); JNDI并行lockup方式獲取,tm.begin() 確定事務, jdbcConn執行update sql,DB寫入binlog,但不更新表,jmsMQ發送消息msg但是不執行提交,dubbo invoke調用遠程服務,provider緩存請求不執行提交,所有提交后捕獲異常rollback。
7,四個dubbo服務,2個失敗則等4個任務全執行完畢后回調,定時任務檢測4個dubbo服務數據是否一致,一致則全部置為成功,不一致則全部置為失敗 。
8,發紅包,推送,統計,分訂單,支付,網銀第三方等異步操作使用最終一致性,重試冪等等,如退款遇到故障會延時退款,保證最終會被完成,不過需要判斷退款保持冪等性,如果發生退款失敗則放入延時隊列,稍后重試。退款操作最終一定會完成。
9,很多交易環節采用MQ來流轉,業務操作上先將訂單持久化到同一個事務里面,共享訂單操作的持久化DB連接,在這個DB連接中將MQ持久化到同一個實例的消息庫中,然后在事務提交之江消息發送到MQ server,事務回滾后消息不會發出去,訂單持久化,MQ持久化到DB,事務提交MQ發出去,發送成功則刪除DB中的消息表記錄,如果發送失敗,后臺有1個任務會將消息表中發送失敗的消息重新發送,達到最終一致性,或者producer是發或者補發,提供1個broker反查接口。也可以采用spring等自帶的MQ事務進行延時重試等。冪等可以采用狀態機,或者攜帶版本號,和DB中的進行對比,后臺掃描制定的時間之內的DB消息表,server段據消息ID做1個去重。
10,A,前者1個嵌入客戶端應用的jar負責事務,數據寫入處理,后者獨立系統,負責異常、事務恢復、2PC需參與者需要一直到持有資源直到整個分布式事務結束,千萬級,性能很差,1個業務服務若干個從,主發起完成整個業務,從作TCC型業務操作,業務活動管理器控制業務活動一致性,登記業務活動中的操作,在活動提交時確認所有的2階段事務的操作,業務取消時可以調用所有2階段事務cancel操作。
B,發起支付,增加用戶積分,調用dubbo支付扣款,支付狀態處理,成功則提交事務,失敗則回調訂單積分,未知則等到支付系統回調狀態。
C,用戶信息變更同步至各業務系統activeMQ中,訂閱方式保證單次消費。
D,非實時非強一致性的業務采用MQ,可以重試和事務消息。
E,事務提交之前插入1條消息記錄,事務提交之后再一步將該消息發出去,成功則將消息記錄刪除,失敗則保留該消息記錄,會有1個服務不斷掃描消息重新發送。
11,跨銀行轉賬,2個異地service服務,構成1個完整事務,事務補償即鏈中每個正向事務必須有1個完全符合回滾的逆向事務,調用本地取款,成功并返回數據已持久化,然后調用異地存款,如失敗則調用本地逆向服務,如本地存服務調用失敗則必須重試,約定重試次數仍然失敗則必須log到完整的不一致信息(也可以MQ),為了避免手工寫大量的代碼,考慮1個通用的事務管理器,實現事務鏈和上下文的管理。任務1個正向和逆向均在事務管理器上注冊,由事務管理器接管所有在事務補償和回滾操作。
消息一致性調用本地取款服務,然后發送MQ,MQ消費對消息解析后調用異步存款服務,失敗則重試,不得已本地取款一般不可逆。(可以存在真空期時間內事務最終一致性)。冪等性重試重復調用多次產生的業務結果和1次調用一樣,因為調用失敗異常必須考慮。
12,一致性結果可能成功,失敗或者不確定,成功就可以把記錄的東西清理掉,對于失敗和不確定,可以依靠定時方式把所有失敗的事情重新嘗試一遍,直到成功為止。系統在A扣錢成功下,把要給B通知這件事記錄到數據庫中,為了保證可靠性可以把通知B系統加錢和扣錢成功這2件事維護在本地1個事務里面,本地事務維護業務變化和通知消息一起落地(失敗則一起回滾),然后RPC到達broker,在broker成功落地后RPC返回成功,本地消息記錄可以刪除,否則本地消息記錄一致靠定時器任務輪詢不斷重發,這樣就保證了消息可靠落地broker。broker一致發消息給consumer,直到consumer確認消費成功,先不理會重復消費,以來狀態機做版本號去重,實現最終一致性。
13,順帶記錄下spring的5中事務方式,每個bean都有1個事務代理;所有bean共享1個事務代理;使用攔截器;使用tx標簽配置的攔截器;全注解方式。
14,創建不可見訂單,同時鎖券,失敗則發送廢棄訂單消息到MQ,然后回庫存和回券,鎖券成功則訂單變為可見。支付系統回調請求會重試到MQ,交易系統會更新交易主子菜單,交付單,減庫存,加銷量,送券等,如果業務失敗則放入重試表,作重試。其中資金作為發起方保證重試和MQ可達。
15,最終一致性,T1發送half消息,T2存儲half消息,T3返回消息入庫結果,T3業務操作,S1定時檢查未提交的消息,S2提交回滾,S3提交更新DB/回滾刪除消息。
16,XA事務:1個數據庫只將其操作(可恢復)映射到全局事務中(交易中間件),由它通知協調相關數據庫的提交和回滾
2PC(二階段):參與者將自己操作成敗通知協調者,再由協調者根據所有參與者反饋情況情報決定參與者是否需要提交操作還是終止。2階段為準備階段和提交階段。分為三個步驟,A協調者節點向所有參與者詢問是否可執行提交,并等待所有參與者響應 B參與者節點詢問發起為止所有事務操作,并將undo和redo寫入日志 C各參與者節點響應協調者發起的詢問,如果參與者節點事務操作實際執行成功,則返回1個同意,參與者操作失敗則返回1個終止。
17,Sagas長事務
在Sagas事務模型中,一個長事務是由一個預先定義好執行順序的子事務集合和他們對應的補償子事務集合組成的。典型的一個完整的交易由T1、T2、……、Tn等多個業務活動組成,每個業務活動可以是本地操作、或者是遠程操作,所有的業務活動在Sagas事務下要么全部成功,要么全部回滾,不存在中間狀態。
Sagas事務模型的實現機制:
每個業務活動都是一個原子操作;
每個業務活動均提供正反操作;
任何一個業務活動發生錯誤,按照執行的反順序,實時執行反操作,進行事務回滾;
回滾失敗情況下,需要記錄待沖正事務日志,通過重試策略進行重試;
沖正重試依然失敗的場景,提供定時沖正服務器,對回滾失敗的業務進行定時沖正;
定時沖正依然失敗的業務,等待人工干預;
Sagas長事務模型支持對數據一致性要求比較高的場景比較適用,由于采用了補償的機制,每個原子操作都是先執行任務,避免了長時間的資源鎖定,能做到實時釋放資源,性能相對有保障。
Sagas長事務方式如果由業務去實現,復雜度與難度并存。在我們實際使用過程中,開發了一套支持Sagas事務模型的框架來支撐業務快速交付。
開發人員:業務只需要進行交易編排,每個原子操作提供正反交易;
配置人員:可以針對異常類型設定事務回滾策略(哪些異常納入事務管理、哪些異常不納入事務管理);每個原子操作的流水是否持久化(為了不同性能可以支持緩存、DB、以及擴展其它持久化方式);以及沖正選項配置(重試次數、超時時間、是否實時沖正、定時沖正等);
Sagas事務框架:提供事務保障機制,負責原子操作的流水落地,原子操作的執行順序,提供實時沖正、定時沖正、事務攔截器等基礎能力;
Sagas框架的核心是IBusinessActivity、IAtomicAction。IBusinessActivity完成原子活動的enlist()、delist()、prepare()、commit()、rollback()等操作;IAtomicAction主要完成對狀態上下文、正反操作執行。
限于文章篇幅,本文不對具體實現做詳述;后面找時間可以詳細介紹基于Sagas長事務模型具體的實現框架。Sagas長事務需要交易提供反操作,支持事務的強一致性,由于沒有在整個事務周期內鎖定資源,對性能影響較小,適合對數據要求比較高的場景中使用。
18,可靠事件模式(本地事件表、外地事件表)
可靠事件模式屬于事件驅動架構,當某件重要事情發生時,例如更新一個業務實體,微服務會向消息代理發布一個事件。消息代理會向訂閱事件的微服務推送事件,當訂閱這些事件的微服務接收此事件時,就可以完成自己的業務,也可能會引發更多的事件發布。
可靠事件模式在于保證可靠事件投遞和避免重復消費,靠事件投遞定義為:
每個服務原子性的業務操作和發布事件;
消息代理確保事件傳遞至少一次;避免重復消費要求服務實現冪等性。
基于事件模式,需要重點考慮的是事件的可靠到達,在我們產品實際支持過程中,通常有本地事件表、外部事件表兩種模式:
1、本地事件表方法將事件和業務數據保存在同一個數據庫中,使用一個額外的“事件恢復”服務來恢復事件,由本地事務保證更新業務和發布事件的原子性。考慮到事件恢復可能會有一定的延時,服務在完成本地事務后可立即向消息代理發布一個事件。
微服務在同一個本地事務中記錄業務數據和事件;
微服務實時發布一個事件立即通知關聯的業務服務,如果事件發布成功立即刪除記錄的事件;
事件恢復服務定時從事件表中恢復未發布成功的事件,重新發布,重新發布成功才刪除記錄的事件;
其中第2條的操作主要是為了增加發布事件的實時性,由第三條保證事件一定被發布。本地事件表方式業務系統和事件系統耦合比較緊密,額外的事件數據庫操作也會給數據庫帶來額外的壓力,可能成為瓶頸。
2、外部事件表方法將事件持久化到外部的事件系統,事件系統需提供實時事件服務以接受微服務發布事件,同時事件系統還需要提供事件恢復服務來確認和恢復事件。
業務服務在事務提交前,通過實時事件服務向事件系統請求發送事件,事件系統只記錄事件并不真正發送;
業務服務在提交后,通過實時事件服務向事件系統確認發送,事件得到確認后,事件系統才真正發布事件到消息代理;
業務服務在業務回滾時,通過實時事件向事件系統取消事件;
如果業務服務在發送確認或取消之前停止服務了怎么辦呢?事件系統的事件恢復服務會定期找到未確認發送的事件向業務服務查詢狀態,根據業務服務返回的狀態決定事件是要發布還是取消;
該方式將業務系統和事件系統獨立解耦,都可以獨立伸縮。但是這種方式需要一次額外的發送操作,并且需要發布者提供額外的查詢接口。
基于可靠事件的事務保障模式可以有很多的變種實現,比如對消息可靠性不高的話,可以將本地表的方式換做緩存方式。為了提高消息投遞的效率,可以將多次消息合并為投遞模式。為了提供強一致性的事務保障,甚至可以將本地消息表持久化(保障發方法消息可靠落地)+遠程消息表持久化(保障接收方消息可靠落地)結合的模式。
在我們的流程產品中針對業務和流程的分布式事務解決方案就采用了多次消息合并投遞+本地緩存+遠程消息表持久化的模式,接下來為大家介紹具體的使用方式。
使用場景
在實際業務項目中通常采用業務與流程分布式部署的模式,業務系統通過遠程接口訪問流程引擎,業務數據同流程數據存放到各自的數據庫中。
在這種場景中,如果業務系統的流程操作和業務操作交叉在一起,當流程操作成功,而業務操作失敗時,就會造成業務回滾,而流程在引擎端已經創建,導致業務系統和流程引擎狀態不一致。
在業務應用中對一個事務中的流程操作采用本地緩存+批量投遞+遠程落地的模式(如果需要在客戶端確保消息可靠性,可以將本地緩存換成本地表的方式);在流程引擎端在消息投遞來之后,做了消息表落地的工作,保障可靠執行。在我們流程產品中流程引擎對外提供的客戶端提供了統一的分布式事務API,和使用傳統本地事務一樣進行操作,保證了透明性,簡化開發人員的復雜度。分布式事務API支持兩種協議模式:
HTTP + 二進制序列化的模式
WebService模式
后續我們會增加Restful風格的接口。
可靠事件模式在互聯網公司中有著較大規模的應用,該方式適合的業務場景非常廣泛,而且能夠做到數據的最終一致性,缺點是該模式實現難度較大,依賴數據庫實現可靠性,在高并發場景下可能存在性能瓶頸,需要在公司層面搭建一套標準的可靠事件框架來支撐。
可靠事件模式(非事務消息、事務消息)
可靠事件模式的事件通知可以采用消息的模式來實現,其實現原理和本地事件表、外部事件表一致,本文就不在詳述。目前常用的消息框架ActiveMQ、RabbitMQ、Kafka、RocketMQ可以用來作為消息投遞的渠道。注意:Kafka通常不適合,因為Kafka的設計存在丟消息的場景。
目前市面上支持事務的消息產品比較少,RocketMQ雖然實現了可靠的事務模式,但并沒有開源出來、沒有開源出來、沒有開源出來,順便說一下國內的開源有太多需要改進的空間(關鍵點不開源,開源后沒有持續的投入)。
就愛閱讀www.92to.com網友整理上傳,為您提供最全的知識大全,期待您的分享,轉載請注明出處。
歡迎轉載:http://www.kanwencang.com/bangong/20161206/63564.html
文章列表