-
1 # 使用者5724249294638
-
2 # 香香33619
這一篇不想談論Hmily原始碼的技術實現,而是想在過了一遍hmily的實現後把hmily的工作思路單獨地整理出來再進行一次總結。看看能不能進一步有所得。
以hmily-demo-springcloud為例,它的實現思路如下。
Hmily事務工作流程
首先它是基於切面程式設計來實現分散式事務的操作,及透過日誌記錄TCC事務的資訊以保證最終一致性。
前端發起的一個請求,第一次進入一個@Hmily註解的函式的時候,就進入Hmily的事務管理了。
這時會進入切面方法,生成一個日誌例項(HmilyTransaction例項)。日誌例項裡面儲存了所有後續需要操作的資訊,比如流轉狀態,執行函式資訊等等,並在後續的操作中會根據需要加入新的資訊。
日誌例項 有一個執行狀態,一開始時是PRE_TRY(開始執行try),並會透過一個併發佇列非同步儲存到資料庫中。順便說一句,每個微服務都有一個日誌表,儲存著對應的日誌。
關於非同步儲存要多說一句,hmily在設計的時候把許多操作,尤其是對日誌表的刪改查操作都改用非同步操作的方式,這也是hmily如此高效的一個原因,值得重點分析。
剛才說到日誌例項被非同步儲存到資料庫的日誌表中了,而另一邊就開始執行我們的業務函式。
如果函式內部再呼叫的函式仍有@Hmily註解,這時候切面裡面不做其他任何操作。
如果呼叫的函式有@Hmily註解且是RPC函式,也就是呼叫其他微服務的代理介面,這時候會把事務id(transId 是事務唯一的,一個分散式事務id只有一個,且被用於日誌主鍵),及當前的角色狀態一起作為請求頭的引數。
被呼叫的微服務接收到請求後,如果執行到帶有@Hmily的函式,會根據傳遞過來的transId 的事務資訊生成又一個事務日誌資訊,狀態為PRE_TRY(開始執行try),並非同步儲存到資料庫中對應該微服務的日誌表中。
接著繼續執行該微服務的主體方法
如果該微服務又呼叫了其它微服務,則同第7步到第12步。
如果執行成功,修改 事務日誌的流轉狀態為TRYING(TRY階段完成),如果失敗了則刪除日誌丟擲異常。
現在回到第一個微服務,如果呼叫成功,會把該rpc介面資訊儲存到日誌資訊裡面。
如果還有呼叫其他微服務,則同第7步到13步。
如果所有的執行都沒問題,這時候會把日誌的狀態改為TRYING(TRY階段完成),然後發起非同步任務執行confirm操作。
confirm操作裡會把狀態改為CONFIRMING(“confirm階段”),並非同步儲存到資料庫中,然後透過反射儲存在日誌裡面的confirmMethod方法,及呼叫rpc介面,將執行confirm的命令傳送給對應的微服務。
其它微服務接收到confirm訊息後,會根據該微服務的事務日誌中儲存的confirmMethod集合,一一執行,或再把該命令傳送給被呼叫的下一層微服務,重複17步驟。
如果各個微服務在執行confirmMethod時,有失敗的案例,會將失敗的confirmMethod重新儲存到對應的事務日誌中,然後隔一定時間透過定時再次執行confirmMethod。直到一一成功或超過重試次數發出資訊給維護人員處理。confirmMethod失敗後的定時執行的這一步各個微服務已經是各自為政了,不用再自上而下的從第一個微服務發起任務。
cancel方法同16步到18步。它的觸發條件是,只要在try階段裡有哪個try出問題了,異常會層層丟擲到最上層,後面的try都不執行。而前面執行過的try資訊或呼叫過的rpc介面資訊都會儲存在事務日誌中間。後面只要同confirm階段一樣,根據這些資訊執行cancelMethod方法或對RPC介面發起cancel請求
-
3 # 使用者3946378225166
它以零侵入以及快速整合方式能夠方便的被業務進行整合。
在效能上,日誌儲存非同步(可選)以及使用非同步執行的方式,不損耗業務方法方法。
之前是由我個人開發,目前由我在京東數科已經重新啟動,未來將會是金融場景的分散式事務解決方案。
回覆列表
它的作用是,每當使用feign呼叫遠端介面時,都會在請求頭中新增上事務上下文資訊
每執行一步,都會即時記錄相應事務狀態,比如執行confirm方法,這時候如果confim執行失敗了,由於相應的事務狀態沒有更新,後端的定時器會不斷查詢失敗的事務,持續呼叫該方法。