eBay推出首個微服務架構下可實現ACID的分布式事務協議:GRIT

19-10-29 banq
                   

eBay技術人員最近展示了一種稱為GRIT的分布式事務協議,用于跨多個具有多個基礎數據庫的微服務進行ACID(原子性,一致性,隔離性,持久性)事務。

本文介紹了GRIT協議的基本思想,該思想在IEEE國際數據工程國際會議(ICDE)2019上宣布,并提供了使用該協議的一部分為JanusGraph實現事務性存儲后端的示例。該示例著重于只有一個數據庫的系統,但是正如我們所說,GRIT可以支持由多個數據庫組成的系統的ACID事務。

背景

微服務體系結構中,應用程序可以調用多個微服務,通常由不同的團隊以不同的應用語言實現這些微服務,并且可以使用多個基礎數據庫來實現其功能。這種流行的架構為跨多個微服務的一致的分布式事務帶來了新的挑戰。在微服務環境中支持ACID事務是一個真正的要求,但是使用現有技術很難實現,因為為單個數據庫設計的分布式事務機制無法通過微服務輕松擴展到具有多個數據庫的情況。

在涉及多個獨立數據庫的環境中,傳統的兩階段提交(2PC)協議1本質上是系統進行分布式事務處理的唯一選擇,而無需額外的應用程序工作。但是,由于潛在的許多協調參與者的路徑很長,并且在階段中需要鎖定,因此在橫向擴展平臺中無法很好地工作。另一方面,使用由?諸如Saga之類的框架2執行的事務日志將招致應用程序復雜的補償邏輯,并且由于不可逆的部分成功的事務而可能產生業務影響。?

為了解決這些問題,我們開發了??GRIT,為全球統一的分布式事務的一個新的協議,它巧妙地結合樂觀并發控制(OCC)、2PC和確定性數據庫等想法 來實現的,這是一個高性能,具有多個基礎數據庫的跨微服務的全局一致事務。

GRIT:一種用于分布式事務的協議

下圖說明了具有兩個數據庫的微服務系統中的GRIT協議。中心顯示了GRIT組件,包括GTM,GTL,DBTM,DBTL和LogPlayer。

  1. 應用程序:調用微服務以實現其功能。
  2. 微服務(實體服務):構建模塊,為應用程序提供面向業務的服務以實現業務邏輯。每個數據庫可能支持多個微服務,并且每個微服務可能彼此獨立。
  3. 數據庫服務:提供數據庫讀寫接口,直接訪問數據庫服務器。當支持事務時,它還在執行階段緩存每個事務的讀/寫結果,并將它們發送到其DBTM以在提交時解決沖突。
  4. 數據庫分片服務器:數據庫的后端存儲服務器,通常進行復制以實現高可用性。

GRIT的關鍵組件包括:

  1. 全局事務管理器(GTM):它協調多個數據庫之間的全局事務。可以有一個或多個GTM。
  2. 全局事務日志(GTL):代表GTM的事務請求隊列。GTL中事務請求的順序確定了全局事務之間的相對可序列化順序。GTL的持久性是可選的。
  3. 數據庫事務管理器(DBTM):每個數據庫領域的事務管理器。它執行沖突檢查和解決,即本地提交決定位于此處。
  4. 數據庫事務日志(DBTL):每個數據庫領域中的事務日志,用于記錄與此數據庫相關的邏輯提交的事務(包括單數據庫事務和多數據庫事務)。DBTL中的事務順序確定整個數據庫系統的可序列化順序,包括GTM規定的全局順序。日志序列號(LSN)被分配給每個日志條目。
  5. LogPlayer:此組件將日志條目按順序發送到后端存儲服務器,以供它們應用更新。每個數據庫服務器按順序應用邏輯提交的事務的日志條目。

為了理解協議的細節,我們使用下圖顯示分布式事務的主要步驟。

在GRIT中,分布式事務經歷三個階段:

  1. 樂觀執行(步驟1-4):當應用程序通過微服務執行業務邏輯時,數據庫服務將捕獲事務的讀集和寫集。在此階段,沒有實際的數據修改發生。
  2. 邏輯提交(步驟5-11):一旦應用程序請求事務提交,每個數據庫服務點的讀集和寫集都將提交到其DBTM。DBTM使用讀集和寫集進行沖突檢查,以實現本地提交決策。GTM將收集DBTM針對事務的所有本地決策后,做出全局提交決策。一旦將其寫集持久保存在所涉及數據庫的日志存儲(DBTL)中,就在邏輯上提交事務。這涉及GTM和DBTM之間的最小協調。
  3. 物理應用(步驟12-13):日志播放器異步將DBTL條目發送到后端存儲服務器。數據修改在此階段進行。?

總的來說,我們的方法避免了在執行和提交過程中的悲觀鎖定,并避免了等待物理提交。我們采用樂觀的方法,并且通過利用邏輯提交日志并使用確定性數據庫技術將物理數據庫更改從提交決策過程中移出,從而使提交過程非常高效,這類似于復制中的日志播放。

GRIT能夠以最小的協調性為調用微服務的應用程序實現一致的高吞吐量和可序列化的分布式事務。GRIT非常適合很少沖突的事務,并為否則需要復雜機制才能在具有多個基礎數據庫的微服務之間實現一致事務的應用程序提供關鍵功能。

將GRIT應用于單個數據庫

如您所見,GRIT協議包含兩個部分:一個部分用于由DBTM,DBTL和LogPlayer執行的每個數據庫(或每個數據庫領域,可以是數據庫的一組分區),另一部分用于跨數據庫協調通過GTM和DBTM。在下圖中,我們使用單個數據庫的GRIT協議部分說明了JanusGraph的事務圖存儲后端(稱為NuGraphStore)的設計。

下圖顯示了如何使用兩個可用區(AZ1和AZ2)部署實施NuGraphStore。

JanusGraph的NuGraphStore后端涉及一些組件:

  • 存儲插件:一個自定義的存儲接口插件,用于在JanusGraph數據庫層與后端存儲引擎和事務協議組件之間建立接口。
  • DBTM:執行關鍵沖突檢查以實現樂觀并發控制。這是執行OCC的單個數據庫上GRIT分布式事務協議的一部分??。
  • LogStore:復制的日志存儲,用于事務的突變。每個事務一個條目,由日志序列號(LSN)索引。在傳統數據庫系統中,它充當WAL(預寫日志)。LogStore是我們GRIT架構中的DBTL。?
  • LogPlayer:異步將日志條目應用于后端服務器。
  • 存儲引擎:后端存儲引擎,用于存儲JanusGraph中的KCV(鍵-列-值)數據。它執行讀取和變異,并支持LSN定義的快照。

當應用程序執行事務時,它可以從store中讀取并寫入store。對于讀取操作,存儲插件直接與存儲服務器通信(除了在事務的寫入集中找到的讀取之外)。當應用程序在事務上下文中從存儲中讀取時,存儲插件還會跟蹤讀取集。每次讀取的有用信息是<key,lsn>對,其中lsn是反映在讀取鍵值時存儲引擎狀態的日志序列號。LSN是事務突變條目的日志索引。它由LogStore分配,用于定義后端數據庫的快照。未找到的鍵key被記錄為讀取集的一部分。與讀取不同,用于寫入的存儲插件不會直接與存儲服務器通信。相反,存儲插件會在事務的相應寫入集中緩沖寫入操作。

事務提交時,存儲插件將提交的請求和已為事務捕獲的讀集和寫集提交給DBTM。DBTM對事務的OCC執行標準沖突檢查。如果沒有沖突,它將把寫集保留到復制的LogStore中(即,它將寫集發送到LogStore副本集,因此所有副本都保持完全相同的日志)。此時,事務提交將在邏輯上完成,并且DBTM將響應存儲插件。LogPlayers跟蹤LogStore,并根據數據分布將日志條目播放到后端分片服務器。

值得指出的是,以上描述是一種基本設計,具有許多提高性能和可靠性的機會。我們相信,在對各個組件進行優化或對DBTM使用復制以實現更高的可靠性之前,使基本組件成熟將更有生產力。同樣,我們可以通過不同的方式捕獲讀集和寫集。對于KV Store,沖突檢查所需的最簡單形式是<key,lsn>對。但是,為了支持更復雜的系統,該讀取集可能包含范圍或謂詞,如第6章所述。?在撰寫本文時,NuGraphStore正在經歷開源過程。

點擊標題參考原文。

?

                   

3
美女漫画大全