seata AT模式實踐

環(huán)境版本:

jdk1.8
maven 3.6
spring-cloud Hoxton.RELEASE
spring-cloud-alibaba 2.1.1.RELEASE
seata-service 0.9
dynamic-datasource-spring-boot-starter 3.0以上

一.簡單調(diào)用

1.1.在全局事務的開始方法加入 @GlobalTransactional 即可

模擬一個報錯的代碼,在第五行斷點,看看各個表的情況

@PostMapping(value = "test-seata")
@GlobalTransactional(rollbackFor = Exception.class)
public void testSeata(@RequestBody @ApiParam HsSaveReq hsSave) throws InterruptedException {
    hsService.saveHs(hsSave);
    int i = 1 / 0;
    log.info("成功");
}

1.2.報錯前

分支事務表

全局事務表

全局鎖

undo_log

undo_log中的rollback_info里面存儲了對象的前后數(shù)據(jù)信息,實踐的時候可以看看

1.3.報錯或者超時(默認6s)的時候

1.正骋羯簦回滾,并刪除3張鎖表的當前事務信息,業(yè)務數(shù)據(jù)回滾(利用undo_log存儲的rollback_info進行反向sql),且異步執(zhí)行
2.臟數(shù)據(jù)回滾不成功,需要人工干預
3.undo_log日志表刪除

1.4.客戶端打印信息

控制臺信息

上面的信息為業(yè)務sql插入
1.打印出了全局事務id(xid),分支id(branchId),seata的模式(branchType),資源編碼(resourceId)
2.undo_log日志刪除刷新
3.AT模式的二階段提交完成
4.回滾狀態(tài):已回滾

二.多服務調(diào)用

需要增加一個 攔截器來傳遞上下服務之間的全局事務id (xid)

2.1.實現(xiàn)WebMvcConfigurer ,重寫 addInterceptors

@Configuration
public class SeataHandlerInterceptorConfiguration implements WebMvcConfigurer {
    public SeataHandlerInterceptorConfiguration() {
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注冊HandlerInterceptor导而,攔截所有請求
        registry.addInterceptor(new SeataHandlerInterceptor()).addPathPatterns(new String[] { "/**" });
    }
}

2.2.實現(xiàn) ClientHttpRequestInterceptor

public class SeataRestTemplateInterceptor implements ClientHttpRequestInterceptor {
    public SeataRestTemplateInterceptor() {
    }

    @Override
    public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes,
            ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
        HttpRequestWrapper requestWrapper = new HttpRequestWrapper(httpRequest);
        String xid = RootContext.getXID();
        if (StringUtils.isNotEmpty(xid)) {
            // 構(gòu)建請求頭
            requestWrapper.getHeaders().add("TX_XID", xid);
        }

        return clientHttpRequestExecution.execute(requestWrapper, bytes);
    }
}

2.3.實現(xiàn)HandlerInterceptor,重寫 preHandle和afterCompletion

@Slf4j
@Configuration
public class SeataHandlerInterceptor implements HandlerInterceptor {

    public SeataHandlerInterceptor() {
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String xid = RootContext.getXID();
        String rpcXid = request.getHeader("TX_XID");
        // 獲取全局事務編號
        if (log.isDebugEnabled()) {
            log.debug("xid in RootContext {} xid in RpcContext {}", xid, rpcXid);
        }

        if (xid == null && rpcXid != null) {
            // 設置全局事務編號
            RootContext.bind(rpcXid);
            if (log.isDebugEnabled()) {
                log.debug("bind {} to RootContext", rpcXid);
            }
        }

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
        String rpcXid = request.getHeader("TX_XID");
        if (StringUtils.isNotEmpty(rpcXid)) {
            String unbindXid = RootContext.unbind();
            if (log.isDebugEnabled()) {
                log.debug("unbind {} from RootContext", unbindXid);
            }

            if (!rpcXid.equalsIgnoreCase(unbindXid)) {
                log.warn("xid in change during RPC from {} to {}", rpcXid, unbindXid);
                if (unbindXid != null) {
                    RootContext.bind(unbindXid);
                    log.warn("bind {} back to RootContext", unbindXid);
                }
            }

        }
    }

}

2.4.業(yè)務編寫,這里調(diào)用采用的是openFeign

@PostMapping(value = "test-seata-ll")
@ApiModelProperty(value = "seata AT模式 多服務調(diào)用回滾")
@GlobalTransactional(rollbackFor = Exception.class)
public void testSeataLl(@RequestBody @ApiParam HsSaveReq hsSave) throws Exception {
    // 模擬 A調(diào)用B,C
    // A,B成功,C失敗情況,看看回滾
    hsService.saveHs(hsSave);
    // 刪除一個存在的記錄
    ResultData<Boolean> B = testProxy.deletePlatformOrgan("1");
    // 刪除一個不存在的記錄
    ResultData<Boolean> C = testProxy.deletePlatformRole("1");
    //可以根據(jù)自己的業(yè)務進行判斷
    if (!"200".equals(B.getCode()) || !"200".equals(C.getCode())) {
        throw new Exception("回滾");
    }
}

也可以看看seata庫中表的情況和undo_log表的情況,也是一致的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌雾叭,老刑警劉巖窝剖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棠隐,死亡現(xiàn)場離奇詭異,居然都是意外死亡瀑晒,警方通過查閱死者的電腦和手機绍坝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門徘意,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苔悦,“玉大人,你說我怎么就攤上這事椎咧【料辏” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵勤讽,是天一觀的道長蟋座。 經(jīng)常有香客問我,道長脚牍,這世上最難降的妖魔是什么向臀? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮诸狭,結(jié)果婚禮上券膀,老公的妹妹穿的比我還像新娘。我一直安慰自己驯遇,他們只是感情好芹彬,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叉庐,像睡著了一般舒帮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天玩郊,我揣著相機與錄音肢执,去河邊找鬼。 笑死译红,一個胖子當著我的面吹牛蔚万,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播临庇,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼反璃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了假夺?” 一聲冷哼從身側(cè)響起淮蜈,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎已卷,沒想到半個月后梧田,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡侧蘸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年裁眯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讳癌。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡穿稳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晌坤,到底是詐尸還是另有隱情逢艘,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布骤菠,位于F島的核電站它改,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏商乎。R本人自食惡果不足惜央拖,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鹉戚。 院中可真熱鬧鲜戒,春花似錦、人聲如沸崩瓤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽却桶。三九已至境输,卻和暖如春蔗牡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嗅剖。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工辩越, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人信粮。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓黔攒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親强缘。 傳聞我的和親對象是個殘疾皇子督惰,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容