乾貨 | 揭秘京東數科強一致、高效能的分散式事務中介軟體JDTX

資料庫頻道發表於2019-10-25

導讀:在分散式資料庫、雲原生資料庫、NewSQL等名詞在資料庫領域層出不窮的當今,變革——在這個相對穩定的領域已愈加不可避免。相比於完全革新,漸進式增強的方案在擁有厚重沉澱的行業則更受青睞。

同所有分散式領域的解決方案相同,分而治之的透明化資料分片方案,是新一代資料庫解決海量資料的核心理念。水平拆分使得分散式事務的重要性,較之垂直拆分的業務系統進一步提升。另外,彈性擴(縮)容、HTAP等概念也是新一代資料庫的關注重點。京東數科開源的Apache ShardingSphere在資料分片方面已逐漸成熟,在此場景之上開發的分散式事務中介軟體JDTX與之共同組成了分散式資料庫的核心拼圖。

JDTX是由京東數科的資料研發團隊傾力打造的分散式事務中介軟體。本次分享是JDTX首次公開出現在大眾視野面前,分享內容涵蓋JDTX的核心設計理念及相關的技術實現難點,希望能為打造分散式事務解決方案的團隊提供一些思路。

背景

資料庫事務需要滿足ACID(原子性、一致性、隔離性、永續性)4個特性。

在單一資料節點中,事務僅限於對單一資料庫資源的訪問控制,稱之為本地事務。幾乎所有的成熟的關係型資料庫都提供了對本地事務的原生支援。但是在基於微服務的分散式應用環境下,越來越多的應用場景要求對多個服務的訪問及其相對應的多個資料庫資源能納入到同一個事務當中,分散式事務應運而生。

關係型資料庫雖然對本地事務提供了完美的ACID原生支援。但在分散式的場景下,它卻成為系統效能的桎梏。如何讓資料庫在分散式場景下滿足ACID的特性或找尋相應的替代方案,是分散式事務的重點工作。

本地事務

在不開啟任何分散式事務管理器的前提下,讓每個資料節點各自管理自己的事務。它們之間沒有協調以及通訊的能力,也並不互相知曉其他資料節點事務的成功與否。本地事務在效能方面無任何損耗,但在強一致性以及最終一致性方面則力不從心。

兩階段提交

XA協議最早的分散式事務模型是由X/Open國際聯盟提出的X/Open Distributed Transaction Processing(DTP)模型,簡稱XA協議。

基於XA協議實現的分散式事務對業務侵入很小。它最大的優勢就是對使用方透明,使用者可以像使用本地事務一樣使用基於XA協議的分散式事務。XA協議能夠嚴格保障事務ACID特性。

嚴格保障事務ACID特性是一把雙刃劍。事務執行在過程中需要將所需資源全部鎖定,它更加適用於執行時間確定的短事務。對於長事務來說,整個事務進行期間對資料的獨佔,將導致對熱點資料依賴的業務系統併發效能衰退明顯。因此,在高併發的效能至上場景中,基於XA協議兩階段提交型別的分散式事務並不是最佳選擇。

柔性事務

如果將實現了ACID的事務要素的事務稱為剛性事務的話,那麼基於BASE事務要素的事務則稱為柔性事務。BASE是基本可用、柔性狀態和最終一致性這3個要素的縮寫。

在ACID事務中對一致性和隔離性的要求很高,在事務執行過程中,必須將所有的資源佔用。柔性事務的理念則是透過業務邏輯將互斥鎖操作從資源層面上移至業務層面。透過放寬對強一致性和隔離性的要求,只要求當整個事務最終結束的時候,資料是一致的。而在事務執行期間,任何讀取操作得到的資料都有可能被改變。這種弱一致性的設計可以用來換取系統吞吐量的提升。Saga和TCC都是典型的柔性事務實現方案。

結論

基於ACID的兩階段事務和基於BASE的最終一致性事務都不是銀彈,可透過下表詳細對比它們之間的區別。


兩階段提交

柔性事務

業務改造

實現相關介面

一致性

支援

最終一致

隔離性

支援

業務方保證

併發效能

嚴重衰退

略微衰退

適合場景

短事務 & 低併發

長事務 & 高併發

缺乏併發度保障的兩階段事務不能稱之為完善的分散式事務解決方案;而缺乏對ACID原義支援的柔性事務都甚至不能稱之為資料庫事務,它更適合服務層的事務處理。

放眼當前,實難找到無需權衡即可放之四海而皆準的分散式事務解決方案。

JDTX的分散式事務解決方案


JDTX的設計目標是強一致(支援ACID的事務原義)、高效能(甚至強於本地事務)、1PC(完全摒棄兩階段提交和兩階段鎖)的完全分散式事務中介軟體,目前可用於關係型資料庫。它採用完全開放SPI的設計方式,提供與NoSQL對接的可能,能夠將多元異構資料維持在同一事務中。

設計理念

首先透過一張架構圖來直觀的瞭解一下JDTX的構成。

乾貨 | 揭秘京東數科強一致、高效能的分散式事務中介軟體JDTX

JDTX由事務管理器(TM)和資源管理器(RM)組成。

事務管理器用於生成全域性單調遞增的事務日誌序列號(LSN),事務的提交和回滾等核心流程處理,以及未提交事務的本地元祖(Tuple)持有。

資源管理器用於管理活躍事務資料。JDTX的設計特點是將在事務中的資料(稱之為活躍資料)和不在事務中的資料(稱之為落盤資料)分離。活躍資料在落盤至預寫日誌系統(WAL)之後,並將資料儲存至自研的多版本快照(MVCC)記憶體引擎中。落盤資料則是透過非同步刷盤的方式,將MVCC引擎中的資料以流量可控的方式同步至最終的儲存介質中(如:關係型資料庫)。

事務內查詢會將落盤資料和活躍資料合併,並根據當前事務的隔離級別獲取出符合當前事務可見性的資料版本。

方案亮點

無損事務方案

JDTX採用WAL + MVCC引擎的方式實現了事務的ACID原義。

原子性&一致性支援

JDTX的 MVCC引擎可以看做是一個集中式快取,可以將兩階段提交簡化至一階段提交。維持單一節點中資料的原子性和一致性,即將分散式事務的範疇縮減到本地事務的範疇。

MVCC引擎可以透過分片 + 主從同步的方式維持水平擴充套件和高可用的能力。JDTX保證所有對事務資料的訪問都透過MVCC引擎的活躍資料 + 最終資料端的落盤資料的合併的方式,以保證資料的原子性和一致性。

隔離性支援

JDTX以多版本快照的方式實現事務隔離性。目前完整的支援4種標準隔離級別中的讀已提交和可重複讀,已經可以滿足絕大部分需求。

永續性支援

JDTX將事務的活躍資料在存入MVCC引擎之前先落盤至WAL引擎,以保證伺服器崩潰,記憶體資料丟失時,活躍資料依然能夠從WAL引擎中完全恢復。

高效能

JDTX採用將活躍資料非同步刷盤至資料庫的方式極大的提高了資料寫入的效能上限。它的效能瓶頸從資料庫寫入耗時轉移到了落盤至WAL引擎和儲存至MVCC引擎的耗時。

與資料庫的WAL系統類似,JDTX的WAL也採用日誌順序追加的方式,因此可以簡單的理解為JDTX的WAL耗時 = 資料庫系統的WAL耗時。而MVCC快取則採用雜湊資料結構,其寫入耗時小於需要維護BTree索引的資料庫寫入耗時。因此,採用JDTX的事務方案,其資料更新效能甚至強於不開啟事務。

另外,JDTX採取了無UNDO日誌的事務回滾策略。未提交的資料並不會進入MVCC引擎,而是被事務管理器本地持有。因此,只要清理掉未提交資料即可完成事務回滾。無UNDO日誌的設計進一步的提升了事務處理的效能。

高可用

WAL引擎和MVCC引擎均採用分片 + 主備的方式,以保證JDTX不會產生單點故障。在MVCC引擎完全不可用的情況下,可透過恢復模式將WAL中的資料同步至資料庫,以保證資料的完整性。

跨多後設資料庫事務

JDTX將事務活躍資料和落盤資料分離的設計方案,使其落盤資料儲存端無任何限制。所有的事務活躍資料都會透過非同步的落盤執行器儲存至後端資料庫,因此後端是否為同構資料庫,其實並無影響。

使用JDTX能夠保證跨多元儲存端(如:MySQL、PostgreSQL甚至是MongoDB、Redis等NoSQL)的分散式事務維持在同一事務語義之中。

實現難點

MVCC核心

事務隔離級別有兩種常見的實現方案,即鎖實現和MVCC實現。除了Infomix等少數資料庫,大部分關係型資料庫均採用MVCC實現。

讀未提交、讀已提交、可重複讀和可序列化這4種事務隔離級別的標準,是ANSI所定義的基於鎖實現的方式。事務的並行度隨著隔離級別的增加而衰減,除了併發度最低的可序列化,其他隔離級別都伴隨著對一致性的權衡和犧牲。

下表是基於鎖實現的隔離級別對照表。

隔離級別

髒讀

不可重複讀

幻讀

讀未提交

可能

可能

可能

讀已提交

不可能

可能

可能

可重複讀

不可能

不可能

可能

可序列化

不可能

不可能

不可能

透過MVCC實現的隔離級別實際上只有SI(快照隔離)和SSI(可序列化快照隔離)這2種。SI和SSI與ANSI的4種隔離級別並不能完全對照。其中的讀未提交,與讀已提交在MVCC的實現中效能並無差別,可以忽略不計。因此SI可以對應為讀已提交和可重複讀這2種隔離級別。實際上,即使是幻讀,在SI隔離級別中也是不會出現的。

由於快照併發控制並不能真正意義上保證事務是“可序列化”的,所以事務間的併發操作依舊有可能引發資料異常現象。但這裡的異常不同於之前提到的髒讀、丟失更新的異常,而是一種業務資料間邏輯語義層面的異常,也可以說是由於未能滿足資料間的語義約束而產生的異常。這被稱之為寫偏序(Write skew),它的檢測可依據併發事務間讀寫依賴的多版本可序列化圖(The multiversion serialization graph)來實現,即SSI隔離級別。

下表是基於MVCC實現的隔離級別對照表。

乾貨 | 揭秘京東數科強一致、高效能的分散式事務中介軟體JDTX

自研MVCC引擎是JDTX的主要難點之一。JDTX採用與PostgreSQL類似的MVCC實現方案,透過xmin和xmax標記事務快照範圍,並在MVCC引擎中儲存每個資料元祖(Tuple)的xmin和xmax的事務資訊。同一資料的多版本以連結串列的資料結構儲存,透過其xmin和xmax來獲取資料的版本在當前事務快照中的可見性。

由於MySQL也並未實現SSI隔離級別,因此目前的JDTX只是實現了SI隔離級別,還並未實現SSI隔離級別。

MVCC資料的清理(vacuum)是另一技術難點。過長的事務會導致MVCC版本過多,導致佔用大量儲存空間。尤其是JDTX是透過記憶體來儲存MVCC的活躍資料,因此對記憶體空間的釋放則更加敏感。由於JDTX的非同步落盤機制,因此除了MVCC標準的垃圾回收邏輯之外,判斷資料是否落盤成為清理邏輯的額外規則。

SQL查詢引擎

透過SQL查詢事務的活躍資料,是JDTX的另一個技術實現難點。MVCC引擎並非關係型資料庫,並不能透過識別SQL來查詢相關資料。JDTX則透過之前Apache ShardingSphere所積累的SQL解析模組及其抽象語法樹(AST)來實現對SQL的理解,以及查詢基於記憶體的MVCC引擎中的資料。

對於SPJ(select-project-join)的OLTP型別SQL,可以從SQL的查詢結果中獲取資料主鍵。JDTX將落盤資料從後端資料庫中取出作為最終展現資料的基礎,並在此之上從MVCC引擎中查詢出當前事務可見的活躍資料,並對其結果進行歸併。換句話說,每次事務內查詢都是由落盤資料+活躍資料歸併而成。歸併引擎部分參照了LSM Tree的設計思想。

對於非SPJ的OLAP型別SQL,JDTX則採用另外的查詢方式。基於聚合函式和分組的SQL無法透過主鍵直接將後端資料庫中的落盤資料和MVCC引擎中的鍵值資料直接匹配,因此採用以MVCC引擎中資料為主,並將SQL改寫為剔除活躍資料主鍵的新SQL,再從後端資料庫中查詢無重複的聚合資料進行歸併。

使用限制

分散式無銀彈,這是架構師們對現有的分散式系統比較公認的看法。雖然JDTX具備了很多優點,但仍然有一些使用限制。它的使用限制主要有以下3點。

  1. 需要透過JDTX訪問資料庫。JDTX透過其MVCC引擎控制事務的原子性、一致性和隔離性,並透過WAL控制事務的永續性。因此在使用JDTX的系統中,跨過事務中介軟體直接查詢資料庫,是得不到正確的事務資料的,修改資料庫則會導致資料紊亂。
  2. SQL支援需要持續完善。查詢MVCC引擎的SQL方言相容則需要持續提升。相對於無損的ACID事務原義支援所帶來的優勢,SQL相容度的下降,是JDTX帶來的權衡。
  3. 不支援無主鍵資料。JDTX需要透過主鍵來合併MVCC引擎和資料庫中的資料。因此無法處理沒有主鍵的記錄。

JDTX與Apache ShardingSphere

透過Apache ShardingSphere提供的JDBC接入端,可以使JDTX無縫的對接至Java應用。除了JDBC接入端,Apache ShardingSphere也提供了基於MySQL和PostgreSQL的Proxy接入端,使JDTX像一個單獨的資料庫一樣提供分散式事務的服務。Apache ShardingSphere將在未來將接入端剝離,使JDTX獨立使用成為可能。
Apache ShardingSphere提供了分散式事務的統一SPI。JDTX透過實現ShardingSphere提供的SPI,可以很輕鬆的融入Apache ShardingSphere生態。結合Apache ShardingSphere與JDTX,可以將資料分片與分散式事務無縫結合。
獨立使用Apache ShardingSphere或JDTX,可以靈活解耦,高度定製,可以看做是基礎元件的樂高積木。而將其聯合使用,則能夠產生化學變化,甚至使它們具備組成分散式資料庫基礎設施的能力。架設在產品最前端的Apache ShardingSphere用於SQL解析、資料庫協議和資料分片;位於中層的JDTX用於透過鍵值對和MVCC的方式處理事務活躍資料;最底層的資料庫則僅作為最終的資料儲存端。下圖是ShardingSphere + JDTX的架構圖。
乾貨 | 揭秘京東數科強一致、高效能的分散式事務中介軟體JDTX

最後附上MySQL架構圖,請讀者自行體會其相似之處。
乾貨 | 揭秘京東數科強一致、高效能的分散式事務中介軟體JDTX

JDTX的後續規劃

JDTX的自身目標是力爭將其打造成為一個分散式事務的標準解決方案。在事務核心流程、MVCC引擎、WAL引擎、高可用等核心功能打磨成熟後,JDTX會將主要精力投放在以下幾個方面:

  1. 提升SQL語句相容性以及多後設資料庫支援;
  2. 實現SSI隔離級別,提供完整的MVCC隔離級別解決方案;
  3. 完善管理端和監控端。

除了JDTX中介軟體自身,它也將與ShardingSphere等其他資料庫中介軟體更加一體化的提供分散式資料庫級別的服務;並將與Kubernetes等雲原生平臺更加深度整合,為雲原生資料庫提供服務。

作者簡介:張亮,京東數科資料研發負責人,Apache ShardingSphere發起人 & PPMC,JDTX負責人。

熱愛開源,主導開源專案ShardingSphere(原名Sharding-JDBC)和Elastic-Job。擅長以java為主分散式架構,推崇優雅程式碼,對如何寫出具有展現力的程式碼有較多研究。

目前主要精力投入在將ShardingSphere和JDTX打造為業界一流的金融級資料解決方案之上。ShardingSphere已經進入Apache孵化器,是京東集團首個進入Apache基金會的開源專案,也是Apache基金會首個分散式資料庫中介軟體。

於2019年3月出版書籍《未來架構——從服務化到雲原生》。

GitHub: ,隨時歡迎技術交流和指正。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31545814/viewspace-2661379/,如需轉載,請註明出處,否則將追究法律責任。

相關文章