Seata:打造行業首個分佈式事務產品

01 微服務架構下數據一致性的挑戰

微服務開發的痛點

在 2019 年,我們基於 Dubbo Ecosystem Meetup,收集了 2000 多份關於“在微服務架構,哪些核心問題是開發者最關注的痛點?”的調研問卷。最終分佈式事務問題在調研中佔比最大,約佔 54%。

在 Seata 出現之前,大家談到分佈式事務的態度是能避則避,大部分是靠寫一些複雜的業務邏輯加消息最終一致性去解決數據一致性問題。但 Seata 開源之後,這些問題都變得簡單起來。比如這裏提到的無損上下線,核心關注的是服務的可用性還是其他問題。從我的理解角度看,我覺得它最終關注的是數據問題。無論前端的業務怎麼去做交互,最終都會沉澱到數據的變化。如果業務的數據不一致,前面無論是什麼樣的架構都變得意義不大,因爲最終數據纔是企業的核心資產。

那麼到底哪些場景會遇到分佈式事務的問題呢?

第一個場景,單體架構在拆分成微服務架構之後,不同的服務可能由不同的團隊維護和負責,這裏會涉及上下游服務的發佈部署聯動。比如 C 服務發佈的時候,並不會通知 A 服務和 B 服務,這個時候就會遇到末端服務上下線帶來的數據一致性問題。

第二個場景,不可靠不穩定的基礎設施帶來的系統穩定性問題進而引發數據一致性問題,比如基礎設施層的存儲、計算和網絡不穩定導致的業務問題等。

第三個場景,timeout 是分佈式架構中服務調用比較難解的狀態,一旦出現服務調用超時,我們無法確定業務邏輯最終是執行了,還是未執行,這裏最終會演化爲數據的一致性的問題。從單體到分佈式架構的演進,服務從進程內調用演變爲跨網絡的調用,在鏈路上糅合網絡的因素,加劇了數據一致性問題的出現的概率。

第四個場景,業務鏈路裏除了會涉及到數據庫,還會涉及到其他第三方的數據組件。比如庫存類服務一般會涉及到 Redis 組件,如何實現數據庫和緩存的數據一致性也是事務鏈路需要考慮的業務場景。

第五個場景,上下游服務調用時,需要在調用鏈路中傳遞一些業務參數,上游服務需要對這些參數做邏輯校驗。當參數邏輯校驗不合法時,如何將上游服務的數據回滾到執行前的數據初態,保證服務調用鏈的數據一致性。

總結起來,分佈式事務的業務場景主要包括跨庫、跨服務和多樣性資源的數據一致性。分佈式事務會尤其關注業務異常導致的事務回滾場景,從異常分類上主要包括業務異常和系統異常。

那麼分佈式事務是不是微服務架構獨有的問題呢?其實不是,它在單體應用裏也有相同的問題,只不過在微服務架構裏這個問題更加凸顯。

在單體架構下存在哪些分佈事務的場景呢?比如一個單體多模塊應用要去操作多個數據庫。本地事務是通過數據庫連接上的一個 SQLSession 完成的,只要跨出了本地事務,那就會涉及到分佈式事務問題,即使不同的微服務去修改同一個數據庫,這也會涉及到分佈式事務問題,因爲 SQLSession 是基於 Socket 連接的,所以它本身是不能通過序列化和反序列化將對象傳遞到其他服務。

整體來看,分佈式事務是各類應用架構的通用問題,應用場景非常廣泛。

分佈式事務的解決方案

市面上的分佈式事務方案有以下幾類:

  • XA 模式,它的性能相比其他事務模式要差一點,但能保證最嚴格的數據一致性。XA 模式需要設置爲串行化隔離級別,相當於對數據添加了讀寫鎖。另外連接資源需要在整個事務期間保持導致資源鎖定問題影響到併發事務的吞吐。
  • TCC 模式和 SAGA 模式,可以歸結爲業務層面的分佈式事務解決方案,因爲它不會攔截數據。比如 TCC 模式有 Try,Confirm 和 Cancel 接口,至於這個接口內的回滾和提交邏輯是業務層面需要去實現的,在框架層面只負責分佈式協調。這要求業務開發對業務邏輯有充分的理解和設計能力,否則可能出現無法提交/回滾、提交和回滾邏輯的不對等、接口的冪等和時序問題 。
  • 消息最終一致性,它最大的優點是可以實現異步化的解耦,同時可以結合消息的削峯填谷的優點。但它本身存在着一些問題,消息更多的是做單向 one way 的通知場景。在一些業務場景中可能存在消息消費失敗的場景,但它無法去回滾消息發送方的數據。比如現金紅包的業務,第一步從我的賬戶扣減紅包金額,第二步通過消息消費的方式提現到我的銀行卡。消息消費的時候我這個賬戶已經被註銷掉了,那麼消息消費即使去重試也會一直處在消費失敗的狀態。對於這類問題,消息是無法再把消息發送方的數據回滾掉。所以,消息適用於一致性要求不強的異步單向通知場景。
  • 定時任務補償,它的學習成本低,但開發成本比較高。尤其是微服務存在多跳節點的鏈路,在任意中間節點出現問題都需要考慮如何去補償和訂正所有已經完成變更的數據,需要補償邏輯編寫的非常詳盡和嚴謹,比較適應於數據一致性和實時性要求不高的簡單業務場景。
  • AT 模式,它對一致性和性能做了綜合考量,主要的特點是簡單無侵入,強一致,學習成本低。缺點是需要遵守一定的開發規約,它並不是對所有的 SQL 類型都支持,有一定的使用限制。適應於通用的業務場景,但它並不適應於熱點數據的高併發場景像 sku 的庫存的扣減。因爲 AT 模式有應用層的全局鎖,當需要對相同的數據修改操作時,需要使用全局鎖控制事務的併發時序,實現上存在鎖排隊等待的機制。

02 分佈式事務 Seata 的架構演進

Seata 的起源

Seata 在阿里內部的產品代號叫 TXC,起源於阿里集團的五彩石項目。五彩石是女媧補天用的石子,當時阿里集團內正在做去 IOE 的架構演進,從單體架構演進到分佈式架構,在演進的過程中必然會涉及到很多的中間件去解決分佈式的問題,TXC 承擔的主要的角色是保證服務的數據一致性。

TXC 和集團內的三大件都做了深度的集成,包括:服務調用框架 HSF 和開源的 Apache Dubbo 相似的一個產品;數據庫層有分庫分表的 TDDL 組件;異步消息的 MetaQ 組件。這三大件基本滿足業務開發的常規需求,TXC 通過深度集成使開發人員無需設計和實現一致性邏輯,框架層面能天然保證一致性對開發人員完全是透明無感知。TXC 在集團內也有廣泛的使用,日均百億級的事務調用,標準 3 節點集羣吞吐量可以達到近 10w TPS。

TXC 產品的 SLA 包括可用性 SLA 和性能 SLA。因爲對於分佈式事務來說,除了要保證基本的數據一致性外,也要保證系統的性能和吞吐量,SLO 指標定義每一次分佈式事務調用額外的 rt 開銷不能超過 xx ms。目前分佈式事務的調用處理已能達到毫秒級,基本接近我們推導的理論上限值,在穩定性上能保證全年無故障。

分佈式事務模型定義

下面我們一起來看下分佈式事務模型的定義。

最開始去定義分佈式事務模型時,我們需要充分考慮分佈式事務應該是在哪一層去實現?

從開發者的視角看應用架構主要包括:最上層是應用開發框架,每個公司都有一套開發框架,可能是自研框架或者 Spring Cloud 體系等。向下一層是服務調用框架由類似 Apache Dubbo 這類的框架承擔,在國內 Apache Dubbo 有着非常廣泛的使用。再向下一層是數據中間件,這層主要包括 ORM 框架、事務、同步、對賬等類型的中間件。最下層是與數據庫的連接層,像 JDBC Java 版本的實現 mysql-connector-java 就屬於這一層。

我們去做了一個簡單的對比,到底應該在哪層實現分佈式事務更合適一些,是在數據庫、數據中間件層還是應用開發框架層?

在應用框架層實現,一致性相對比較弱。因爲在開發框架層糅合了比較多的複雜的因素,比如會把服務調用的異常給糅合進去。比如服務調用的超時和重試機制,這就是爲什麼現在 TCC 模式它會有一些冪等、防懸掛和空回滾問題,因爲融入了 RPC 的因素,所以會帶來一些不確性問題。實際上,Seata 已經在框架層面解決了這類的問題。

在數據中間件層,它的一致性比應用框架要好,它存在主要的問題是因爲不在數據庫層實現,所以是有辦法繞過中間件直接去修改數據庫的,這時候就會存在事務併發髒寫問題,歸根到底是因爲數據中間件不是修改數據的唯一界面,但可以通過一定的開發規約來規範使用避免問題的產生。

最好的數據一致性是在數據庫層去實現,但在數據庫層實現面臨的主要問題是:

1. 主要依賴數據庫廠商的實現,能力上參差不齊。比如 MySQL 在 5.7.7 版本才把XA做到真正可用,在之前的版本它對 XA prepare 持久化一直存在問題。

2. 無法約束跨服務的分佈式事務。數據庫層實現的分佈式事務以數據庫爲核心資源,作用範圍只能侷限在數據庫本身。如果要在更大的 scope 下做分佈式事務,比如應用要跨服務,對於跨服務的分佈式事務它就無法約束,所以還是需要有一個第三方的協調者從全局去協調跨服務的數據一致性。

最終,我們把差異化的 AT 事務模式做到了數據庫中間件層,TCC 和 Saga 事務模式做到了應用開發框架層。

分佈式事務模型定義不僅僅只是定義一個開發組件,它除了要實現了一整套的開發流程體系,還要包括了對編程模型的定義,性能,運維,安全,數據審計,可觀測和高可用體系等。在理論模型上,最初我們的理論是比較匱乏的,後續逐步完善了角色模型的定義和 Spring 事務模型的延展。之所以是去延展了已有的模型,而不是完全新創造一套理論體系是因爲這樣做對開發者能大幅度降低學習的成本。此外,我們還做了一些基礎理論的定義,包括一致性的定義,是解決多節點的一致性,還是業務應用架構數據的一致性,事務的模式定義,事務交互模型和事務的隔離性等。

什麼是分佈式事務,它在日常中解決了什麼問題?

舉個例子,我去做銀行轉賬的時候,我給你轉 100 元,恰好這個時候出現了網絡超時,那麼這 100 元到底有沒有扣減。如果不確定就可能出現資損的問題,甚至可能影響企業的商譽。

我們都在談分佈式架構,但從整個應用的宏觀視角,實際上並不是所有組件都是分佈式的。比如從一個應用的架構的層面去看數據庫,當然也包括今天流行的分佈數據庫,從整個應用層面來看它還是一個集中式的數據的存儲。在分佈式的應用架構裏,每個節點都只掌握了部分的信息,如果要做一些問題的排查,必然需要一個集中式的組件掌握全鏈路的信息。對於分佈式事務它的核心工作是做分佈式協調,所以它需要掌握全局的事務和數據信息。

這就是爲什麼 Seata 有了 Transaction Coordinator 角色,對分佈式事務,它要有一個上帝視角,充當第三方的協調器,真正去執行數據庫操作的是 Resource Manager,你可以認爲它是數據庫的靈魂,充當了數據庫的 Proxy。真正隨着業務應用去做事務控制的是 Transaction Manager,它伴隨着業務的執行鏈路去控制事務的邊界和決議。Transaction Coordinator,Resource Manager 和 Transaction Manager 共同構成了分佈式事務的角色模型。

分佈式事務的架構演進

2019 年 1 月 Seata 正式開源,從 0.1 版本我們將主打的 AT 事務模式開源,0.4 版本正式納入了 TCC 事務模式。AT 模式需要適配不同的數據庫進行開發,在現有階段很難滿足對所有關係數據庫的支持,以及業務鏈路的緩存資源支持,這就需要 TCC 事務模式去做 AT 事務模式的補充。

隨着 Seata 的不斷迭代和發佈,對長事務解決方案的呼聲越來越強。在 0.9 版本正式納入 Saga 事務模式,它主要解決鏈路較長的微服務數據一致性問題,同時兼顧了微服務的可視化編排。在 1.1 版本,Seata 納入了 XA 的事務模式。爲什麼納入 XA 模式?Seata 支持了 AT、TCC 和 Saga 事務模式之後,市面上其他的事務模式主要包括消息最終一致性和 XA 模式。社區也陸續收到了用戶的一些聲音的反饋,用戶在較新的業務中使用了 AT 事務模式,用戶期望可以和原有的 XA 模式可以實現互聯互通,形成統一的分佈式事務選型。

Seata 通過社區驅動的模式推動技術的演進,打造了一站式的分佈式事務的解決方案。針對不同的業務場景,Seata 都能使用不同事務模式滿足業務的需求。如上圖所示,爲什麼 Seata 要有四種事務模式?目前市面上沒有一種分佈事務的模式,能解決不同業務場景的數據一致性問題。

分佈式事務是一款和業務耦合比較深的組件,從數據交互鏈路上看包括同步和異步,長事務和短事務,強一致和弱一致以及與性能的權衡考量。所以社區納入了現在的四種事務模式,它們從改造成本、性能和隔離性上各有所長,這裏就不展開介紹了。

03 如何基於 Seata 擴展 RPC 和數據庫

Seata 開源社區現狀

首先看一下 Seata 開源社區發展的現狀。Seata 已經納入了 AT、TCC、Saga、XA 四種事務模式,對於市面上主流的關係數據庫和 RPC 框架做了廣泛的支持,同時也被許多第三方社區做了主動和被動集成,目前已經和三十多個社區做了開源生態上的集成,這些集成依賴於 Seata 現有的可插拔擴展機制設計。

Seata 有着豐富的多語言生態體系,除了最開始的 Java 版本,對 Golang 的支持也變得越來越成熟,歡迎大家去試用 Golang 版本,給社區提出更多寶貴的意見和建議。另外,社區還在建設多語言版本包括 PHP、Python 等。

目前 Seata 開源產品已被上千家企業在業務系統中應用,金融企業也紛紛試點。金融類的業務對分佈式事務的需求是強需求,而且對產品的各項能力要求非常嚴苛。像中信銀行、光大銀行、農行與社區也建立了合作,使用 Seata 陸續改造它們的一些核心賬務系統,保證賬務體系的數據一致性。這也一定程度上反映了 Seata 開源產品的成熟度。

目前 Seata 社區的 Star 數已經到達了 24k,contributor 超 300 多人。Seata 是非常開放的一個社區,非常歡迎大家能夠參與到 Seata 社區的建設中。

Seata 企業實踐案例

接下來介紹一些 Seata 比較典型的企業案例。

第一個案例:中航信航旅縱橫項目。中航信是 Seata 最早的天使用戶,接入的是 Seata 0.2 版本。如果大家出差比較頻繁,應該會用到它們航旅縱橫的 APP。中航信使用 Seata 解決機票和優惠券業務的數據一致性問題,在最早期的版本中,用戶陪社區踩了不少坑。

第二個案例:滴滴出行二輪車事業部。它在 Seata 0.6.1 版本引入到了二輪車事業部的各個業務中,包括市面上大家看到青桔單車和內部資產的管理。

第三個案例:美團基礎架構。美團基礎架構團隊基於開源 Seata 封裝了內部分佈式事務 Swan 項目,作爲美團內部各業務解決分佈式事務問題的基礎組件。

第四個案例:盒馬小鎮。盒馬小鎮遊戲互動中通過 Seata 控制採花偷花的流程,開發週期從原有的 20 天下降至 5 天,大幅度減少了開發的成本。綜上可以發現分佈式事務的兩大價值。

  • 業務數據的正確性,因爲只有數據一致再談架構纔有意義。
  • 提升開發效率,架構師和開發者可以專注於業務的設計和開發而無需關注數據一致性的問題。

Seata 生態擴展

上圖是 Seata 開放生態擴展點的分層結構。最上層定義了 API 這一層,中間這一層包括註冊配置中心、AT 數據庫資源、分佈式鎖和負載均衡策略等,下層包括集羣的存儲模式,SQLParser,協議層和傳輸控制。在集羣模式中支持無狀態的基於 DB 或 Redis 的存儲模式,此外社區正在做基於 Raft 的存算不分離的集羣模式。

Seata 可插拔擴展點

Seata 在定義可插拔的擴展機制參考了 Dubbo SPI 的設計。Seata 的擴展點分爲 Server 擴展點和 Client 擴展點。Client 擴展點大概有 30+ 個主要面向配置,服務註冊發現,鑑權,SQL 解析和執行器等。Server 側的擴展點包括鎖、存儲、事務模式的處理。

從當前 Seata 的擴展機制來看,比如你要去支持一個國產信創數據庫如達夢、人大金倉,二次開發的成本是比較低的。只需要按照社區提供的文檔,對現有的 SQL 解析和執行器 SPI 進行對應數據庫的實現和配置加載,就能把整個流程跑起來。Seata 對市面上常見的 RPC 框架和關係數據庫做了擴展實現。

Seata & RPC 集成擴展

目前 Seata 已經支持了 11 種常見的 RPC 框架,對 Dubbo 的適配社區支持了早期的 Alibaba Dubbo 版本和後續的 Apache Dubbo 版本。Seata 和 RPC 框架的集成比較輕量,核心是要把 Seata 的事務上下文通過服務調用鏈路傳遞到服務的上游,並對事務上下文的綁定和清除等操作。Seata 可以在 RPC 框架提供的 request/response 擴展點實現上述 Seata 的擴展邏輯,常見的 RPC 框架基本支持自定義 filter 或 interceptor 的加載。

右邊是當前實現 RPC 接口擴展的樣例,歡迎大家在 Dubbo 的生態去使用 Seata 去解決跨服務的數據一致性問題。

Seata & 數據庫集成擴展

目前 Seata AT 模式數據庫支持 MySQL、Oracle、PostgreSQL、TiDB、OceanBase、SQLServer 等數據庫。社區仍有一些數據庫適配相關的 PR 當前還在 review 狀態中,未合併到主幹中像達夢和 IBM DB2 等。就像剛纔提到的,只要基於當前的數據庫的擴展點去做對應的實現,就能實現尚未在社區支持的關係數據庫適配。在近期的編程之夏活動中,社區提了 PolarDB 課題的支持,目前也已進入到測試狀態,後續社區將完整的支持 top20 的關係數據庫,同時也將增加對信創數據庫的支持。

總結

Seata 起源於阿里內部電商業務體系,解決服務化過程中的服務一致性問題,經過了多年標準化建設和大促流量的洗禮,Seata 已成爲交易、支付和物流場景的標準化組件。Seata 開源後,通過社區驅動的方式加速技術的探索和演進,致力於打造一站式的分佈式事務解決方案,囊括了 AT、TCC、Saga 和 XA 多種事務模式,滿足不同場景的用戶需求。Seata 在社區生態上做了大量的集成與被集成,通過插件化的方案預留了豐富的擴展點,滿足不同場景的用戶對服務調用框架、數據庫和註冊配置中心的擴展需求。展望未來,Seata 社區立足於分佈式事務解決方案來繼續完善其生態,同時將探索和延展更廣闊的 DataOPS 生態。

作者:季敏,阿里雲分佈式事務產品負責人、Seata 開源項目創始人

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章