微服務架構應滿足資料最終一致性,實現最終一致性的三種模式:可靠事件模式、補償模式、tcc模式。
事務補償機制
事務補償即在事務鏈中的任何乙個正向事務操作,都必須存在乙個完全符合回滾規則的可逆事務。如果是乙個完整的事務鏈,則必須事務鏈中的每乙個業務服務或操作都有對應的可逆服務。
實現真正的預提交和正式提交的分離。
需要手工編寫大量的**來處理以保證事務的完整性。
考慮實現乙個通用的事務管理器,實現事務鏈和事務上下文的管理。對於事務鏈上的任何乙個服務正向和逆向操作均在事務管理和協同器上註冊,由事務管理器接管所有的事務補償和回滾操作。
base策略中的基於訊息的最終一致性是比較好的解決方案。
補償模式
第一部分:實現補償模式的關鍵在於業務流水的記錄;要實現補償過程,我們需要做到兩點
1、首先要確定失敗的步驟和狀態,從而確定需要補償的範圍。
2、其次要能提供補償操作使用到的業務資料。
關聯表,分為框架表和業務表,技術表中儲存為實現補償操作所需要的技術資料,業務表儲存業務資料,通過在技術表中增加業務表名和業務表主鍵來建立和業務資料的關聯。
第二部分:通過重試來保證補償過程的完整,從而滿足最終一致性。
補償過程作為乙個服務呼叫過程同樣存在呼叫不成功的情況,這個時候需要通過重試的機制來保證補償的成功率。當然這也就要求補償操作本身具備冪等性(重試就要保證冪等)。
不同的重試策略
如果只是一味的失敗就立即重試會給工作服務造成不必要的壓力,我們要根據服務執行失敗的原因來選擇不同的重試策略。(重試也有不同的策略)
1)如果失敗的原因不是暫時性的,由於業務因素導致(如業務要素檢查失敗)的業務錯誤,這類錯誤是不會重發就能自動恢復的,那麼應該立即終止重試。(引數錯誤)
2)如果錯誤的原因是一些罕見的異常,比如因為網路傳輸過程出現資料丟失或者錯誤,應該立即再次重試,因為類似的錯誤一般很少會再次發生。(網路抖動,在發生網路抖動時可以進行自動地補償呼叫)
3)如果錯誤的原因是系統繁忙(比如http協議返回的500或者另外約定的返回碼)或者超時,這個時候需要等待一些時間再重試。(響應超時)
重試操作一般會指定重試次數上線,如果重試次數達到了上限就不再進行重試了。這個時候應該通過一種手段通知相關人員進行處理。
對於等待重試的策略如果重試時仍然錯誤,可逐漸增加等待的時間,直到達到乙個上限後,以上限作為等待時間。
如果某個時刻聚集了大量需要重試的操作,補償框架需要控制請求的流量,以防止對工作服務造成過大的壓力。
補償模式補充說明
1.微服務實現補償操作不是簡單的回退到業務發生時的狀態,因為可能還有其他的併發的請求同時更改了狀態。一般都使用逆操作的方式完成補償。
2.補償過程不需要嚴格按照與業務發生的相反順序執行,可以依據工作服務的重用程度優先執行,甚至是可以併發的執行。
tcc模式是優化的補償模式。
1、所有事務參與方都需要實現try,confirm,cancle介面。
2、事務發起方向事務協調器發起事務請求,事務協調器呼叫所有事務參與者的try方法完成資源的預留,這時候並沒有真正執行業務,而是為後面具體要執行的業務預留資源,這裡完成了一階段。
3、如果事務協調器發現有參與者的try方法預留資源時候發現資源不夠,則呼叫參與方的cancle方法回滾預留的資源,需要注意cancle方法需要實現業務冪等,因為有可能呼叫失敗(比如網路原因參與者接受到了請求,但是由於網路原因事務協調器沒有接受到回執)會重試。
4、如果事務協調器發現所有參與者的try方法返回都ok,則事務協調器呼叫所有參與者的confirm方法,不做資源檢查,直接進行具體的業務操作。
5、如果協調器發現所有參與者的confirm方法都ok了,則分布式事務結束。
6、如果協調器發現有些參與者的confirm方法失敗了,或者由於網路原因沒有收到回執,則協調器會進行重試。這裡如果重試一定次數後還是失敗,會怎麼樣那?常見的是做事務補償。
與補償模式不同的是tcc服務框架不需要記錄詳細的業務流水,完成confirm和cancel操作的業務要素由業務服務提供。
傳送訊息之前就開始儲存這些資訊。
介面補償還是kafka傳送訊息的補償,這兩者記錄的字段不一樣,對錶設計有影響。
協調服務為乙個通用的補償框架。
補償模式表設計
create table `data_send_status` (
`id` int(11) not null auto_increment comment 'id',
`flow_id` int(11) not null comment '對應業務id',
`service_type` tinyint(4) not null comment '1表示支付服務呼叫訂單服務',
`send_topic` varchar(255) default null comment '傳送對應topic',
`send_params` varchar(255) default null comment '引數',
`error_msg` varchar(255) default null comment '錯誤資訊',
`is_prepare` tinyint(4) not null default '0' comment '0表示準備傳送,1表示傳送結束',
`is_success` tinyint(4) not null default '0' comment '0表示傳送失敗,1表示傳送成功',
`delete_flag` int(1) not null comment '刪除標誌',
`created_id` int(11) not null comment '建立人id',
`created_time` datetime not null comment '建立時間',
`modified_id` int(11) not null comment '修改人id',
`modified_time` datetime not null comment '修改時間',
primary key (`id`)
) engine=innodb default charset=utf8 comment='資料傳送狀態記錄表';
create table `data_auto_compensation` (
`id` int(11) not null auto_increment comment 'id',
`data_send_id` int(11) not null comment '資料傳送失敗的記錄id',
`retry_count` int(11) not null default '0' comment '重試次數',
`max_retry_count` int(11) not null default '3' comment '最大重試次數',
`status` int(11) not null comment '狀態 0未解決 1已解決',
`delete_flag` int(1) not null comment '刪除標誌',
`created_id` int(11) not null comment '建立人id',
`created_time` datetime not null comment '建立時間',
`modified_id` int(11) not null comment '修改人id',
`modified_time` datetime not null comment '修改時間',
primary key (`id`)
) engine=innodb default charset=utf8 comment='資料補償表';
2020 04 27 最近不在狀態555
最近感覺複習很無力,我希望我可以盡量往樂觀的方面去想,有問題就解決問題有毛病就改,有錯就改。考研路漫漫,而我還在起點觀望 考研就像一場沒有硝煙的戰爭,作為這場戰爭裡面很渺小的一員,有些時候感覺自己就是在簡單地進行機械的學習,就像就只是在接受老師或書本給我傳達得一些資訊,而我對這些資訊的加工並不多。對...
智慧型時代模式轉型 硬體虧損服務補償
智慧型時代新型商業模式的轉型一直是大家努力探索的目標,雖然至今鮮有成功者。9月28日亞馬遜發布平板電腦,售價199美元,有分析師 亞馬遜的平板每台要虧損50美元 在剛剛結束的通訊展上中興通訊的員工說智慧型手機賣到500萬台可以掙錢 近期引起 及消費者矚目的小公尺手機目標是不虧錢 聯想平板電腦a1近期...
擦除的補償
擦除丟失了在泛型 中執行某些操作的能力,任何在執行時需要知道確切型別資訊的操作都將無法進行,通過型別標籤來對擦除進行補償。package com.cognizant.ch15 class building class house extends building public class class...