最近研究了一下分布式事務框架,ttc,總體感覺還可以,當然前提條件下是你要會使用這個框架。下面分層次講,盡量讓想學習的同學讀了這篇文章能加以操作運用。我不想廢話,直接上干貨。
一.什么是tcc?干什么用的?
ttc是分布式事務框架,用於分布式事務的。分布式事務就是針對兩個以上的庫操作數據事務管理的,比如操作A庫B庫,當B庫失敗,也要把A庫哪一步操作也要回滾。
ttc其實是一個模板框架,是英文字母try,confirm,cnacel三個單詞的縮寫。我們要操作的業務處理部分在try里面執行,執行的所有結果是否有失敗的情況在confirm里面確認,如果有失敗,則在cancel里面做回滾操作。不要問我什么是回滾操作,回滾操作就是比如你增加了一條數據,回滾就指你去刪掉這條數據。相信已經夠直白了。
二.模板什么樣子?怎么使用?
首先我貼出模板框架,大概TccTemplate,TccResult,TccCallBack,TranslationTask 四個類
public class TccTemplate {
private static final Logger logger = LoggerFactory.getLogger(TccCallBack.class);
/**
* 分布式事務模板
*
* @param tccCallBack 分布式事務執行回調
* @param method 當前方法名(封裝參數, 可方便撈取數據)
*/
public static TccResult process(TccCallBack tccCallBack, String method) {
// 返回一個消息用於
TccResult tccResult = new TccResult();
String msg = "";
try {
// 執行主業務
tccCallBack.tryExecute();
// 進行確認執行結果,如果結果是false,則執行回滾操作
boolean confirm = tccCallBack.confirm();
if (confirm) {
tccResult.setStatus(true);
msg = String.format("分布式事務{%s}執行成功", method);
logger.info(msg);
} else {
tccResult.setStatus(false);
msg = String.format("分布式事務{%s}執行失敗,進行回滾操作", method);
logger.warn(msg);
tccCallBack.cancel();
}
} catch (BizException e) {
// 主流程發生異常, 則直接執行回滾操作
tccResult.setStatus(false);
tccResult.setCode(e.getErrorCode().getCode());
msg = e.getMessage();
logger.warn(String.format("分布式事務{%s}執行發生異常,進行回滾操作", method), e);
tccCallBack.cancel();
throw e;
}catch (BusinessException e) {
// 主流程發生異常, 則直接執行回滾操作
tccResult.setStatus(false);
tccResult.setCode(e.getErrorCode());
msg = e.getErrorMessage();
logger.warn(String.format("分布式事務{%s}執行發生異常,進行回滾操作", method), e);
tccCallBack.cancel();
throw e;
} catch (Exception e) {
// 主流程發生異常, 則直接執行回滾操作
tccResult.setCode(BizErrorCodeEnum.UNSPECIFIED.getCode());
tccResult.setStatus(false);
msg = e.getMessage();
logger.warn(String.format("分布式事務{%s}執行發生異常,進行回滾操作", method), e);
tccCallBack.cancel();
throw e;
} finally {
// 返回結果Result
tccResult.setMsg(msg);
return tccResult;
}
}
}
框架種用到的類也給大家貼出來:
public class TccResult<T> {
private String code;
/** 響應數據 */
private T data;
/** 響應狀態 */
private Boolean status = true;
/** 響應消息 */
private String msg;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
public interface TccCallBack {
/**
* 執行主要分布式業務操作
*/
void tryExecute();
/**
* 確認分布式業務操作最終結果,
* 如果返回true,則不執行cancel,返回false則執行cancel
*/
boolean confirm();
/**
* 取消操作
*/
void cancel();
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TranslationTask {
private String name;
private Object parameter;
}
新學習這個框架的同學,可以先在項目里面建立一個文件夾,然后把這四個類copy進去,然后在你需要用到的地方,直接用就行,具體使用,舉例子,我也直接來干貨。
比如我想在test方法里面用到分布式事務,用偽代碼表示具體邏輯,下單在訂單庫,用戶在用戶庫
public Boolean test(Map<String, String> inParams) {
//把操作成功的結果放進這里
Stack<Object> taskStack = new Stack<>();
//暫存分布式結果
HashMap<String,Boolean > tempResult = Maps.newHashMap();
// 分布式事務調用
TccResult process = TccTemplate.process(new TccCallBack() {
@Override
public void tryExecute() {
boolean flag=false;
1.下單,生成訂單id
if(訂單id不為空){
taskStack.push(new TranslationTask("1",訂單id));
flag=true;
}else{
flag=false;
}
2.下單成功后,改用戶狀態
if(flag){
修改用戶狀態
}
if(修改用戶狀態成功){
flag=true;
}else{
flag=false;
}
tempResult.put("result", flag);
}
@Override
public boolean confirm() {
return tempResult.get("result") == true ;
}
@Override
public void cancel() {
for (int i = 0; i < taskStack.size(); i++) {
TranslationTask translationTask = (TranslationTask) taskStack.pop();
switch (translationTask.getName()) {
case "1":
訂單id = translationTask.getParameter();
根據訂單id刪除生成的訂單
break;
default:
break;
}
}
}
}, "分布式事務測試");
return tempResult.get("result");
}
上面偽代碼其實就是指先下單,下單成功的話,把結果裝到taskStack里面,裝到這里是為了用於取出數據回滾用。然后還有個tempResult,這個類的作用目的在於把每一步的結果放進去,用於確認的,如果有一步失敗,將會回滾操作
如果有疑問,請留言,或者喜歡請給個關注,我會持續為大家用盡量通俗的話,不講廢話,把好的東西分享出來。