<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實(shí)戰(zhàn)!阿里神器 Seata 實(shí)現(xiàn) TCC模式 解決分布式事務(wù)!

          共 7366字,需瀏覽 15分鐘

           ·

          2022-01-19 14:34

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)??


            今天這篇文章介紹一下Seata如何實(shí)現(xiàn)TCC事務(wù)模式,文章目錄如下:

            目錄

            什么是TCC模式?

            TCC(Try Confirm Cancel)方案是一種應(yīng)用層面侵入業(yè)務(wù)的兩階段提交。是目前最火的一種柔性事務(wù)方案,其核心思想是:針對(duì)每個(gè)操作,都要注冊(cè)一個(gè)與其對(duì)應(yīng)的確認(rèn)和補(bǔ)償(撤銷)操作

            TCC分為兩個(gè)階段,分別如下:

            • 第一階段:Try(嘗試),主要是對(duì)業(yè)務(wù)系統(tǒng)做檢測(cè)及資源預(yù)留 (加鎖,鎖住資源)
            • 第二階段:本階段根據(jù)第一階段的結(jié)果,決定是執(zhí)行confirm還是cancel
              1. Confirm(確認(rèn)):執(zhí)行真正的業(yè)務(wù)(執(zhí)行業(yè)務(wù),釋放鎖)
              2. Cancle(取消):是預(yù)留資源的取消(出問題,釋放鎖)
            TCC

            為了方便理解,下面以電商下單為例進(jìn)行方案解析,這里把整個(gè)過(guò)程簡(jiǎn)單分為扣減庫(kù)存,訂單創(chuàng)建 2 個(gè)步驟,庫(kù)存服務(wù)和訂單服務(wù)分別在不同的服務(wù)器節(jié)點(diǎn)上。

            假設(shè)商品庫(kù)存為 100,購(gòu)買數(shù)量為 2,這里檢查和更新庫(kù)存的同時(shí),凍結(jié)用戶購(gòu)買數(shù)量的庫(kù)存,同時(shí)創(chuàng)建訂單,訂單狀態(tài)為待確認(rèn)。

            ①Try 階段

            TCC 機(jī)制中的 Try 僅是一個(gè)初步操作,它和后續(xù)的確認(rèn)一起才能真正構(gòu)成一個(gè)完整的業(yè)務(wù)邏輯,這個(gè)階段主要完成:

            • 完成所有業(yè)務(wù)檢查( 一致性 ) 。
            • 預(yù)留必須業(yè)務(wù)資源( 準(zhǔn)隔離性 ) 。
            • Try 嘗試執(zhí)行業(yè)務(wù)。
            Try階段

            ②Confirm / Cancel 階段

            根據(jù) Try 階段服務(wù)是否全部正常執(zhí)行,繼續(xù)執(zhí)行確認(rèn)操作(Confirm)或取消操作(Cancel)。

            Confirm 和 Cancel 操作滿足冪等性,如果 Confirm 或 Cancel 操作執(zhí)行失敗,將會(huì)不斷重試直到執(zhí)行完成。

            Confirm:當(dāng) Try 階段服務(wù)全部正常執(zhí)行, 執(zhí)行確認(rèn)業(yè)務(wù)邏輯操作,業(yè)務(wù)如下圖:

            Try->Confirm

            這里使用的資源一定是 Try 階段預(yù)留的業(yè)務(wù)資源。在 TCC 事務(wù)機(jī)制中認(rèn)為,如果在 Try 階段能正常的預(yù)留資源,那 Confirm 一定能完整正確的提交。

            Confirm 階段也可以看成是對(duì) Try 階段的一個(gè)補(bǔ)充,Try+Confirm 一起組成了一個(gè)完整的業(yè)務(wù)邏輯。

            Cancel:當(dāng) Try 階段存在服務(wù)執(zhí)行失敗, 進(jìn)入 Cancel 階段,業(yè)務(wù)如下圖:

            Try-Cancel

            Cancel 取消執(zhí)行,釋放 Try 階段預(yù)留的業(yè)務(wù)資源,上面的例子中,Cancel 操作會(huì)把凍結(jié)的庫(kù)存釋放,并更新訂單狀態(tài)為取消。

            以上便是TCC模式的全部概念

            TCC模式的三種類型?

            業(yè)內(nèi)實(shí)際生產(chǎn)中對(duì)TCC模式進(jìn)行了擴(kuò)展,總結(jié)出了如下三種類型,其實(shí)從官方的定義中無(wú)此說(shuō)法,不過(guò)是企業(yè)生產(chǎn)中根據(jù)實(shí)際的需求衍生出來(lái)的三種方案。

            1、通用型 TCC 解決方案

            通用型TCC解決方案是最經(jīng)典的TCC事務(wù)模型的實(shí)現(xiàn),正如第一節(jié)介紹的模型,所有的從業(yè)務(wù)都參與到主業(yè)務(wù)的決策中。

            通用型TCC

            適用場(chǎng)景

            由于從業(yè)務(wù)服務(wù)是同步調(diào)用,其結(jié)果會(huì)影響到主業(yè)務(wù)服務(wù)的決策,因此通用型 TCC 分布式事務(wù)解決方案適用于執(zhí)行時(shí)間確定且較短的業(yè)務(wù),比如電商系統(tǒng)的三個(gè)核心服務(wù):訂單服務(wù)、賬戶服務(wù)、庫(kù)存服務(wù)。

            這個(gè)三個(gè)服務(wù)要么同時(shí)成功,要么同時(shí)失敗。

            當(dāng)庫(kù)存服務(wù)、賬戶服務(wù)的第二階段調(diào)用完成后,整個(gè)分布式事務(wù)完成。

            2、異步確保型 TCC 解決方案

            異步確保型 TCC 解決方案的直接從業(yè)務(wù)服務(wù)是可靠消息服務(wù),而真正的從業(yè)務(wù)服務(wù)則通過(guò)消息服務(wù)解耦,作為消息服務(wù)的消費(fèi)端,異步地執(zhí)行。

            異步確保型

            可靠消息服務(wù)需要提供 Try,Confirm,Cancel 三個(gè)接口。Try 接口預(yù)發(fā)送,只負(fù)責(zé)持久化存儲(chǔ)消息數(shù)據(jù);Confirm 接口確認(rèn)發(fā)送,這時(shí)才開始真正的投遞消息;Cancel 接口取消發(fā)送,刪除消息數(shù)據(jù)。

            消息服務(wù)的消息數(shù)據(jù)獨(dú)立存儲(chǔ),獨(dú)立伸縮,降低從業(yè)務(wù)服務(wù)與消息系統(tǒng)間的耦合,在消息服務(wù)可靠的前提下,實(shí)現(xiàn)分布式事務(wù)的最終一致性。

            此解決方案雖然增加了消息服務(wù)的維護(hù)成本,但由于消息服務(wù)代替從業(yè)務(wù)服務(wù)實(shí)現(xiàn)了 TCC 接口,從業(yè)務(wù)服務(wù)不需要任何改造,接入成本非常低。

            適用場(chǎng)景:

            由于從業(yè)務(wù)服務(wù)消費(fèi)消息是一個(gè)異步的過(guò)程,執(zhí)行時(shí)間不確定,可能會(huì)導(dǎo)致不一致時(shí)間窗口增加。因此,異步確保性 TCC 分布式事務(wù)解決方案只適用于對(duì)最終一致性時(shí)間敏感度較低的一些被動(dòng)型業(yè)務(wù)(從業(yè)務(wù)服務(wù)的處理結(jié)果不影響主業(yè)務(wù)服務(wù)的決策,只被動(dòng)的接收主業(yè)務(wù)服務(wù)的決策結(jié)果)。比如會(huì)員注冊(cè)服務(wù)和郵件發(fā)送服務(wù):

            3、補(bǔ)償型 TCC 解決方案

            補(bǔ)償型 TCC 解決方案與通用型 TCC 解決方案的結(jié)構(gòu)相似,其從業(yè)務(wù)服務(wù)也需要參與到主業(yè)務(wù)服務(wù)的活動(dòng)決策當(dāng)中。但不一樣的是,前者的從業(yè)務(wù)服務(wù)只需要提供 Do 和 Compensate 兩個(gè)接口,而后者需要提供三個(gè)接口。

            Do 接口直接執(zhí)行真正的完整業(yè)務(wù)邏輯,完成業(yè)務(wù)處理,業(yè)務(wù)執(zhí)行結(jié)果外部可見;Compensate 操作用于業(yè)務(wù)補(bǔ)償,抵消或部分抵消正向業(yè)務(wù)操作的業(yè)務(wù)結(jié)果,Compensate操作需滿足冪等性。

            與通用型解決方案相比,補(bǔ)償型解決方案的從業(yè)務(wù)服務(wù)不需要改造原有業(yè)務(wù)邏輯,只需要額外增加一個(gè)補(bǔ)償回滾邏輯即可,業(yè)務(wù)改造量較小。但要注意的是,業(yè)務(wù)在一階段就執(zhí)行完整個(gè)業(yè)務(wù)邏輯,無(wú)法做到有效的事務(wù)隔離,當(dāng)需要回滾時(shí),可能存在補(bǔ)償失敗的情況,還需要額外的異常處理機(jī)制,比如人工介入。

            適用場(chǎng)景

            由于存在回滾補(bǔ)償失敗的情況,補(bǔ)償型 TCC 分布式事務(wù)解決方案只適用于一些并發(fā)沖突較少或者需要與外部交互的業(yè)務(wù),這些外部業(yè)務(wù)不屬于被動(dòng)型業(yè)務(wù),其執(zhí)行結(jié)果會(huì)影響主業(yè)務(wù)服務(wù)的決策。

            以上部分內(nèi)容參考自:https://seata.io/zh-cn/blog/tcc-mode-applicable-scenario-analysis.html?utm_source=gold_browser_extension

            TCC事務(wù)模式的落地實(shí)現(xiàn)

            當(dāng)然Seata支持的事務(wù)模式不局限于AT模式,還有TCC模式、SAGA模式、XA模式,下面整合一下TCC模式。

            1、演示場(chǎng)景

            就以電商系統(tǒng)中下訂單為例,為了演示,直接去掉賬戶服務(wù),以訂單服務(wù)、庫(kù)存服務(wù)為例介紹。

            具體的邏輯如下:

            1. 客戶端調(diào)用下訂單接口
            2. 扣庫(kù)存
            3. 創(chuàng)建訂單
            4. 請(qǐng)求完成

            根據(jù)上面的邏輯可知,訂單服務(wù)肯定是主業(yè)務(wù)服務(wù),事務(wù)的發(fā)起方,庫(kù)存服務(wù)是從業(yè)務(wù)服務(wù),參與事務(wù)的決策。

            Seata的AT模式解決方案?jìng)未a如下:

            @GlobalTransactional
            public?Result?createOrder(Long?productId,Long?num,.....){
            ????//1、扣庫(kù)存
            ????reduceStorage();
            ????//2、創(chuàng)建訂單
            ????saveOrder();
            }

            @GlobalTransactional這個(gè)注解用于發(fā)起一個(gè)全局事務(wù)。

            但是AT模式有局限性,如下:

            • 性能低,鎖定資源時(shí)間太長(zhǎng)
            • 無(wú)法解決跨應(yīng)用的事務(wù)

            因此對(duì)于要求性能的下單接口,可以考慮使用TCC模式進(jìn)行拆分成兩階段執(zhí)行,這樣整個(gè)流程鎖定資源的時(shí)間將會(huì)變短,性能也能提高。

            此時(shí)的TCC模式的拆分如下:

            1、一階段的Try操作

            TCC模式中的Try階段其實(shí)就是預(yù)留資源,在這個(gè)過(guò)程中可以將需要的商品數(shù)量的庫(kù)存凍結(jié),這樣就要在庫(kù)存表中維護(hù)一個(gè)凍結(jié)的庫(kù)存這個(gè)字段。

            偽代碼如下:

            @Transactional
            public?boolean?try(){
            ??//凍結(jié)庫(kù)存
            ??frozenStorage();
            ??//生成訂單,狀態(tài)為待確認(rèn)
            ??saveOrder();
            }

            注意:@Transactional開啟了本地事務(wù),只要出現(xiàn)了異常,本地事務(wù)將會(huì)回滾,同時(shí)執(zhí)行第二階段的cancel操作。

            2、二階段的confirm操作

            confirm操作在一階段try操作成功之后提交事務(wù),涉及到的操作如下:

            1. 釋放try操作凍結(jié)的庫(kù)存(凍結(jié)庫(kù)存-購(gòu)買數(shù)量)
            2. 生成訂單

            偽代碼如下:

            @Transactional
            public?boolean?confirm(){
            ????//釋放掉try操作預(yù)留的庫(kù)存
            ????cleanFrozen();
            ????//修改訂單,狀態(tài)為已完成
            ????updateOrder();
            ????return?true;
            }

            注意:這里如果返回false,遵循TCC規(guī)范,應(yīng)該要不斷重試,直到confirm完成。

            3、二階段的cancel操作

            cancel操作在一階段try操作出現(xiàn)異常之后執(zhí)行,用于回滾資源,涉及到的操作如下:

            1. 恢復(fù)凍結(jié)的庫(kù)存(凍結(jié)庫(kù)存-購(gòu)買數(shù)量、庫(kù)存+購(gòu)買數(shù)量)
            2. 刪除訂單

            偽代碼如下:

            @Transactional
            public?boolean?cancel(){
            ????//釋放掉try操作預(yù)留的庫(kù)存
            ????rollbackFrozen();
            ????//修改訂單,狀態(tài)為已完成
            ????delOrder();
            ????return?true;
            }

            注意:這里如果返回false,遵循TCC規(guī)范,應(yīng)該要不斷重試,直到cancel完成。

            2、TCC事務(wù)模型的三個(gè)異常

            實(shí)現(xiàn)TCC事務(wù)模型涉及到的三個(gè)異常是不可避免的,實(shí)際生產(chǎn)中必須要規(guī)避這三大異常。

            1、空回滾

            定義:在未調(diào)用try方法或try方法未執(zhí)行成功的情況下,就執(zhí)行了cancel方法進(jìn)行了回滾。

            怎么理解呢?未調(diào)用try方法就執(zhí)行了cancel方法,這個(gè)很容易理解,既然沒有預(yù)留資源,那么肯定是不能回滾。

            try方法未執(zhí)行成功是什么意思?

            可以看上節(jié)中的第一階段try方法的偽代碼,由于try方法開啟了本地事務(wù),一旦try方法執(zhí)行過(guò)程中出現(xiàn)了異常,將會(huì)導(dǎo)致try方法的本地事務(wù)回滾(注意這里不是cancel方法回滾,而是try方法的本地事務(wù)回滾),這樣其實(shí)try方法中的所有操作都將會(huì)回滾,也就沒有必要調(diào)用cancel方法。

            但是實(shí)際上一旦try方法拋出了異常,那么必定是要調(diào)用cancel方法進(jìn)行回滾,這樣就導(dǎo)致了空回滾。

            解決方案

            解決邏輯很簡(jiǎn)單:在cancel方法執(zhí)行操作之前,必須要知道try方法是否執(zhí)行成功。

            2、冪等性

            TCC模式定義中提到:如果confirm或者cancel方法執(zhí)行失敗,要一直重試直到成功。

            這里就涉及了冪等性,confirm和cancel方法必須保證同一個(gè)全局事務(wù)中的冪等性。

            解決方案

            解決邏輯很簡(jiǎn)單:對(duì)付冪等,自然是要利用冪等標(biāo)識(shí)進(jìn)行防重操作。

            3、懸掛

            事務(wù)協(xié)調(diào)器在調(diào)用 TCC 服務(wù)的一階段 Try 操作時(shí),可能會(huì)出現(xiàn)因網(wǎng)絡(luò)擁堵而導(dǎo)致的超時(shí),此時(shí)事務(wù)管理器會(huì)觸發(fā)二階段回滾,調(diào)用 TCC 服務(wù)的 Cancel 操作,Cancel 調(diào)用未超時(shí);

            在此之后,擁堵在網(wǎng)絡(luò)上的一階段 Try 數(shù)據(jù)包被 TCC 服務(wù)收到,出現(xiàn)了二階段 Cancel 請(qǐng)求比一階段 Try 請(qǐng)求先執(zhí)行的情況,此 TCC 服務(wù)在執(zhí)行晚到的 Try 之后,將永遠(yuǎn)不會(huì)再收到二階段的 Confirm 或者 Cancel ,造成 TCC 服務(wù)懸掛。

            解決方案

            解決邏輯很簡(jiǎn)單:在執(zhí)行try方法操作資源之前判斷cancel方法是否已經(jīng)執(zhí)行;同樣的在cancel方法執(zhí)行后要記錄執(zhí)行的狀態(tài)。

            4、總結(jié)

            針對(duì)以上三個(gè)異常,落地的解決方案很多,比如維護(hù)一個(gè)事務(wù)狀態(tài)表,每個(gè)事務(wù)的執(zhí)行階段全部記錄下來(lái)。

            • 冪等:在執(zhí)行confirm或者cancel之前根據(jù)事務(wù)狀態(tài)表查詢當(dāng)前全局事務(wù)是否已經(jīng)執(zhí)行過(guò)confirm或者cancel方法
            • 空回滾:在執(zhí)行cancel之前才能根據(jù)事務(wù)狀態(tài)表查詢當(dāng)前全局事務(wù)是否已經(jīng)執(zhí)行成功try方法
            • 懸掛:在執(zhí)行try方法之前,根據(jù)事務(wù)狀態(tài)表查詢當(dāng)前全局事務(wù)是否已經(jīng)執(zhí)行過(guò)cancel方法

            Seata整合TCC實(shí)現(xiàn)

            關(guān)于如何搭建項(xiàng)目、添加依賴這里就不再細(xì)說(shuō)了

            本節(jié)只介紹關(guān)鍵代碼,畢竟篇幅有限,其他部分請(qǐng)自行下載源碼。

            案例源碼地址:https://github.com/chenjiabing666/JavaFamily/tree/master/cloud-alibaba/seata-tcc

            源碼目錄如下:

            源碼目錄

            項(xiàng)目啟動(dòng)所需要的相關(guān)文件如下圖:

            nacos目錄中的SEATA_GROUP是Seata事務(wù)服務(wù)端和客戶端所需要的相關(guān)配置,直接導(dǎo)入nacos即可。

            seata目錄中的conf是1.3.0版本服務(wù)端的配置

            SQL目錄是相關(guān)的幾個(gè)數(shù)據(jù)庫(kù)。

            1、TCC接口定義

            order-boot模塊創(chuàng)建OrderTccService,代碼如下:

            代碼中注釋已經(jīng)很完整了,下面挑幾個(gè)重點(diǎn)介紹一下:

            1. @LocalTCC:該注解開啟TCC事務(wù)
            2. @TwoPhaseBusinessAction:該注解標(biāo)注在try方法上,其中的三個(gè)屬性如下:
              1. name:TCC事務(wù)的名稱,必須是唯一的
              2. commitMethod:confirm方法的名稱,默認(rèn)是commit
              3. rollbackMethod:cancel方法的名稱,,默認(rèn)是rollback
            3. confirm和cancel的返回值尤為重要,返回false則會(huì)不斷的重試。

            2、TCC接口實(shí)現(xiàn)

            定義有了,總要實(shí)現(xiàn),如下:

            1、try方法

            try方法

            處的代碼是為了防止懸掛異常,從事務(wù)日志表中獲取全局事務(wù)ID的狀態(tài),如果是cancel狀態(tài)則不執(zhí)行。

            處的代碼凍結(jié)庫(kù)存

            處的代碼生成訂單,狀態(tài)為待確認(rèn)

            處的代碼向冪等工具類中添加一個(gè)標(biāo)記,key當(dāng)前類全局事務(wù)IDvalue為當(dāng)前時(shí)間戳。

            注意:必須要開啟本地事務(wù),如上代碼使用@Transactional開啟本地事務(wù)

            2、confirm方法

            confirm方法

            處的代碼從冪等工具類中根據(jù)當(dāng)前類和全局事務(wù)ID獲取值,由于try階段執(zhí)行成功會(huì)向其中添加值,confirm方法執(zhí)行成功會(huì)移出這個(gè)值,因此在confirm開頭判斷這個(gè)值是否存在就起到了冪等效果,防止重試的效果。

            處的代碼從冪等工具類中移出try方法中添加的值。

            處的代碼是從BusinessActionContext中獲取try方法中的入?yún)ⅰ?/p>

            處的代碼是釋放掉凍結(jié)的庫(kù)存

            處的代碼是修改訂單的狀態(tài)為已完成。

            注意:1. 開啟本地事務(wù) ?2. 注意返回值,返回false時(shí)將會(huì)重試

            3、cancel方法

            cancel方法

            處的代碼是向事務(wù)日志記錄表中插入一條數(shù)據(jù),標(biāo)記當(dāng)前事務(wù)進(jìn)入cancel方法,用來(lái)防止懸掛,這個(gè)和try方法中的處的代碼相呼應(yīng)。

            處的代碼是為了防止冪等和空回滾,因?yàn)橹挥挟?dāng)try方法中執(zhí)行成功冪等工具類中對(duì)應(yīng)的當(dāng)前類和全局事務(wù)ID才會(huì)存儲(chǔ)該值。這樣既防止了冪等,也防止了空回滾。

            處的代碼恢復(fù)凍結(jié)的庫(kù)存。

            處的代碼刪除這筆訂單

            處的代碼是移出冪等工具類當(dāng)前類和全局事務(wù)ID對(duì)應(yīng)的值。

            3、如何防止TCC模型的三個(gè)異常?

            實(shí)現(xiàn)方法有很多,有些案例是全部使用事務(wù)日志表記錄當(dāng)前的狀態(tài),這樣完美的解決了冪等、空回滾、懸掛的問題。

            陳某這里為了方便,使用了兩種方案,如下:

            1、冪等、空回滾

            使用了一個(gè)冪等工具類,其中是個(gè)Map,key為當(dāng)前類和全局事務(wù)ID,value是時(shí)間戳。

            代碼如下:

            思路如下:

            1. 在try方法最后使用冪等工具類中的add方法添加值
            2. 在confirm、cancel方法中使用冪等工具類中的remove方法移出值
            3. 在confirm、cancel方法中使用冪等工具類中g(shù)et方法獲取值,如果為空,則表示已經(jīng)執(zhí)行過(guò)了,直接返回true,這樣既防止了冪等,也防止了空回滾。

            2、懸掛

            懸掛的實(shí)現(xiàn)依靠的是事務(wù)日志表,表結(jié)構(gòu)如下:

            CREATE?TABLE?`transactional_record`?(
            ??`id`?bigint(11)?NOT?NULL?AUTO_INCREMENT,
            ??`xid`?varchar(100)?NOT?NULL,
            ??`status`?int(1)?DEFAULT?NULL?COMMENT?'1.?try??2?commit?3?cancel?',
            ??PRIMARY?KEY?(`id`)?USING?BTREE
            )?ENGINE=InnoDB?DEFAULT?CHARSET=utf8mb4;

            其中的xid是全局事務(wù)ID,status是事務(wù)的狀態(tài)。

            其他的字段自己可以擴(kuò)展

            解決懸掛問題的邏輯如下:

            1. cancel方法中將當(dāng)前全局事務(wù)ID記錄到事務(wù)日志表中,狀態(tài)為cancel
            2. try方法執(zhí)行資源操作前檢查事務(wù)日志表中當(dāng)前全局事務(wù)ID是否已經(jīng)是cancel狀態(tài)

            4、創(chuàng)建訂單的業(yè)務(wù)方法

            上面只是完成了TCC的三個(gè)方法,主業(yè)務(wù)事務(wù)發(fā)起方還未提供,代碼如下:

            @GlobalTransactional這個(gè)注解開啟了全局事務(wù),是事務(wù)的發(fā)起方。

            內(nèi)部直接調(diào)用的TCC的try方法。

            5、其他的配置

            以上只是列出了關(guān)鍵的步驟,剩余其他的配置自己根據(jù)案例源碼完善,如下:

            1. 接口測(cè)試
            2. 整合nacos
            3. 整合feign
            4. 整合seata,TCC模式中的配置和AT模式的Seata配置相同

            注意:一定要配置Seata的事務(wù)組tx-service-group,配置方法見之前的文章。

            6、總結(jié)

            TCC事務(wù)模型相對(duì)來(lái)說(shuō)比較簡(jiǎn)單的一種,有興趣的可以下載源碼試試。

            案例源碼地址:https://github.com/chenjiabing666/JavaFamily/tree/master/cloud-alibaba/seata-tcc

            1.?Nginx從安裝到高可用,一篇搞定!

            2.?SpringBoot + Elasticsearch7.6實(shí)現(xiàn)簡(jiǎn)單查詢及高亮分詞查詢

            3.?從零入門 SpringSecurity

            4.?2021 全球程序員收入報(bào)告出爐,看完我真的拖后腿了。。

            最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

            獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

            PS:因公眾號(hào)平臺(tái)更改了推送規(guī)則,如果不想錯(cuò)過(guò)內(nèi)容,記得讀完點(diǎn)一下在看,加個(gè)星標(biāo),這樣每次新文章推送才會(huì)第一時(shí)間出現(xiàn)在你的訂閱列表里。

            點(diǎn)“在看”支持小哈呀,謝謝啦??!

            瀏覽 20
            點(diǎn)贊
            評(píng)論
            收藏
            分享

            手機(jī)掃一掃分享

            分享
            舉報(bào)
            評(píng)論
            圖片
            表情
            推薦
            點(diǎn)贊
            評(píng)論
            收藏
            分享

            手機(jī)掃一掃分享

            分享
            舉報(bào)
            <kbd id="afajh"><form id="afajh"></form></kbd>
            <strong id="afajh"><dl id="afajh"></dl></strong>
              <del id="afajh"><form id="afajh"></form></del>
                  1. <th id="afajh"><progress id="afajh"></progress></th>
                    <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    国产精品黄视频 | 91干视频在线观看 | 狠狠躁日日躁夜夜躁av | 双飞精品一区二区三区 | 国产豆花视频在线观看 |