強!分庫分表與分散式資料庫技術選項分析

朱小廝的部落格發表於2022-12-08


來源:rrd.me/gEhKy


最近經常被問到分庫分表與分散式資料庫如何選擇,網上也有很多關於中介軟體+傳統關聯式資料庫(分庫分表)與NewSQL分散式資料庫的文章,但有些觀點與判斷是我覺得是偏激的,脫離環境去評價方案好壞其實有失公允。

本文透過對兩種模式關鍵特性實現原理對比,希望可以儘可能客觀、中立的闡明各自真實的優缺點以及適用場景。

NewSQL資料庫先進在哪兒?

首先關於“中介軟體+關聯式資料庫分庫分表”算不算NewSQL分散式資料庫問題,國外有篇論文pavlo-newsql-sigmodrec[1],如果根據該文中的分類,Spanner、TiDB、OB算是第一種新架構型,Sharding-Sphere、Mycat、DRDS等中介軟體方案算是第二種(文中還有第三種雲資料庫,本文暫不詳細介紹)。

基於中介軟體(包括SDK和Proxy兩種形式)+傳統關聯式資料庫(分庫分表)模式是不是分散式架構?我覺得是的,因為儲存確實也分散式了,也能實現橫向擴充套件。但是不是"偽"分散式資料庫?從架構先進性來看,這麼說也有一定道理。"偽"主要體現在中介軟體層與底層DB重複的SQL解析與執行計劃生成、儲存引擎基於B+Tree等,這在分散式資料庫架構中實際上冗餘低效的。為了避免引起真偽分散式資料庫的口水戰,本文中NewSQL資料庫特指這種新架構NewSQL資料庫。

NewSQL資料庫相比中介軟體+分庫分表的先進在哪兒?畫一個簡單的架構對比圖:

強!分庫分表與分散式資料庫技術選項分析
  1. 傳統資料庫面向磁碟設計,基於記憶體的儲存管理及併發控制,不如NewSQL資料庫那般高效利用。
  2. 中介軟體模式SQL解析、執行計劃最佳化等在中介軟體與資料庫中重複工作,效率相比較低;
  3. NewSQL資料庫的分散式事務相比於XA進行了最佳化,效能更高;
  4. 新架構NewSQL資料庫儲存設計即為基於paxos(或Raft)協議的多副本,相比於傳統資料庫主從模式(半同步轉非同步後也存在丟數問題),在實現了真正的高可用、高可靠(RTO<30s,RPO=0)
  5. NewSQL資料庫天生支援資料分片,資料的遷移、擴容都是自動化的,大大減輕了DBA的工作,同時對應用透明,無需在SQL指定分庫分表鍵。

這些大多也是NewSQL資料庫產品主要宣傳的點,不過這些看起來很美好的功能是否真的如此?接下來針對以上幾點分別闡述下的我的理解。

分散式事務

首先要說的就是分散式事務:這是一把雙刃劍。

CAP限制

想想更早些出現的NoSQL資料庫為何不支援分散式事務(最新版的mongoDB等也開始支援了),是缺乏理論與實踐支撐嗎?並不是,原因是CAP定理依然是分散式資料庫頭上的頸箍咒,在保證強一致的同時必然會犧牲可用性A或分割槽容忍性P。為什麼大部分NoSQL不提供分散式事務?[2]

那麼NewSQL資料庫突破CAP定理限制了嗎?並沒有。NewSQL資料庫的鼻主Google Spanner(目前絕大部分分散式資料庫都是按照Spanner架構設計的)提供了一致性和大於5個9的可用性,宣稱是一個“實際上是CA”的,其真正的含義是系統處於CA狀態的機率高由於網路分割槽導致的服務停用的機率非常小,究其真正原因是其打造私有全球網保證了不會出現網路中斷引發的網路分割槽,另外就是其高效的運維隊伍,這也是cloud spanner的賣點。詳細可見CAP提出者Eric Brewer寫的《Spanner, TrueTime 和CAP理論[3]》。

推薦一篇關於分散式系統有趣的文章,站在巨人的分散式肩膀上[4],其中提到:分散式系統中,您可以知道工作在哪裡,或者您可以知道工作何時完成,但您無法同時瞭解兩者;兩階段協議本質上是反可用性協議。

完備性

兩階段提交協議是否嚴格支援ACID,各種異常場景是不是都可以覆蓋?

2PC在commit階段傳送異常,其實跟最大努力一階段提交類似也會有部分可見問題,嚴格講一段時間內並不能保證A原子性和C一致性(待故障恢復後recovery機制可以保證最終的A和C)。完備的分散式事務支援並不是一件簡單的事情,需要可以應對網路以及各種硬體包括網路卡、磁碟、CPU、記憶體、電源等各類異常,透過嚴格的測試。之前跟某友商交流,他們甚至說目前已知的NewSQL在分散式事務支援上都是不完整的,他們都有案例跑不過,圈內人士這麼篤定,也說明了分散式事務的支援完整程度其實是層次不齊的

但分散式事務又是這些NewSQL資料庫的一個非常重要的底層機制,跨資源的DML、DDL等都依賴其實現,如果這塊的效能、完備性打折扣,上層跨分片SQL執行的正確性會受到很大影響。

效能

傳統關聯式資料庫也支援分散式事務XA,但為何很少有高併發場景下用呢?因為XA的基礎兩階段提交協議存在網路開銷大,阻塞時間長、死鎖等問題,這也導致了其實際上很少大規模用在基於傳統關聯式資料庫的OLTP系統中。

NewSQL資料庫的分散式事務實現也仍然多基於兩階段提交協議,例如google percolator分散式事務模型,採用原子鐘+MVCC+ Snapshot Isolation(SI)這種方式透過TSO(Timestamp Oracle)保證了全域性一致性,透過MVCC避免了鎖,另外透過primary lock和secondary lock將提交的一部分轉為非同步,相比XA確實提高了分散式事務的效能。

SI是樂觀鎖,在熱點資料場景,可能會大量的提交失敗。另外SI的隔離級別與RR並無完全相同,它不會有幻想讀,但會有寫傾斜。

但不管如何最佳化,相比於1PC,2PC多出來的GID獲取、網路開銷、prepare日誌持久化還是會帶來很大的效能損失,尤其是跨節點的數量比較多時會更加顯著例如在銀行場景做個批次扣款,一個檔案可能上W個賬戶,這樣的場景無論怎麼做還是吞吐都不會很高。

Spanner給出的分散式事務測試資料:強!分庫分表與分散式資料庫技術選項分析

雖然NewSQL分散式資料庫產品都宣傳完備支援分散式事務,但這並不是說應用可以完全不用關心資料拆分,這些資料庫的最佳實踐中仍然會寫到,應用的大部分場景儘可能避免分散式事務。

既然強一致事務付出的效能代價太大,我們可以反思下是否真的需要這種強一致的分散式事務?尤其是在做微服務拆分後,很多系統也不太可能放在一個統一的資料庫中。嘗試將一致性要求弱化,便是柔性事務,放棄ACID(Atomicity,Consistency, Isolation, Durability),轉投BASE(Basically Available,Soft state,Eventually consistent)例如Saga、TCC、可靠訊息保證最終一致等模型,對於大規模高併發OLTP場景,我個人更建議使用柔性事務而非強一致的分散式事務。關於柔性事務,筆者之前也寫過一個技術元件,最近幾年也湧現出了一些新的模型與框架,比如阿里的Seata。有關分散式事務的詳細介紹,如2PC、3PC、XA、AT、Saga、TCC、Seata等概念可以參考我(公眾號:朱小廝的部落格)之前寫的兩篇文章:《分散式事務科普|初識篇》和《分散式事務科普|終結篇》

解決分散式事務是否只能用兩階段提交協議? oceanbase1.0中透過updateserver避免分散式事務的思路很有啟發性 ,不過2.0版後也變成了2PC。業界分散式事務也並非只有兩階段提交這一解,也有其它方案its-time-to-move-on-from-two-phase(如果打不開,國內有翻譯版)

HA與異地多活

主從模式並不是最優的方式,就算是半同步複製,在極端情況下(半同步轉非同步)也存在丟數問題,目前業界公認更好的方案是基於paxos分散式一致性協議或者其它類paxos如raft方式,Google Spanner、TiDB、cockcoachDB、OB都採用了這種方式,基於Paxos協議的多副本儲存,遵循過半寫原則,支援自動選主,解決了資料的高可靠,縮短了failover時間,提高了可用性,特別是減少了運維的工作量,這種方案技術上已經很成熟,也是NewSQL資料庫底層的標配。當然這種方式其實也可以用在傳統關聯式資料庫,阿里、微信團隊等也有將MySQL儲存改造支援paxos多副本的,MySQL也推出了官方版MySQL Group Cluster,預計不遠的未來主從模式可能就成為歷史了。

分散式一致性演算法本身並不難,但具體在工程實踐時,需要考慮很多異常並做很多最佳化,實現一個生產級可靠成熟的一致性協議並不容易。例如實際使用時必須轉化實現為multi-paxos或multi-raft,需要透過batch、非同步等方式減少網路、磁碟IO等開銷。

需要注意的是很多NewSQL資料庫廠商宣傳基於paxos或raft協議可以實現【異地多活】,這個實際上是有前提的,那就是異地之間網路延遲不能太高。 以銀行“兩地三中心”為例,異地之間多相隔數千裡,延時達到數十毫秒,如果要多活,那便需異地副本也參與資料庫日誌過半確認,這樣高的延時幾乎沒有OLTP系統可以接受的。

資料庫層面做異地多活是個美好的願景,但距離導致的延時目前並沒有好的方案。 之前跟螞蟻團隊交流,螞蟻異地多活的方案是在應用層透過MQ同步雙寫交易資訊,異地DC將交易資訊儲存在分散式快取中,一旦發生異地切換,資料庫同步中介軟體會告之資料延遲時間,應用從快取中讀取交易資訊,將這段時間內涉及到的業務物件例如使用者、賬戶進行黑名單管理,等資料同步追上之後再將這些業務物件從黑名單中剔除。由於雙寫的不是所有資料庫操作日誌而只是交易資訊,資料延遲隻影響一段時間內資料,這是目前我覺得比較靠譜的異地度多活方案。

另外有些系統進行了單元化改造,這在paxos選主時也要結合考慮進去,這也是目前很多NewSQL資料庫欠缺的功能。

Scale橫向擴充套件與分片機制

paxos演算法解決了高可用、高可靠問題,並沒有解決Scale橫向擴充套件的問題,所以分片是必須支援的。NewSQL資料庫都是天生內建分片機制的,而且會根據每個分片的資料負載(磁碟使用率、寫入速度等)自動識別熱點,然後進行分片的分裂、資料遷移、合併,這些過程應用是無感知的,這省去了DBA的很多運維工作量。以TiDB為例,它將資料切成region,如果region到64M時,資料自動進行遷移。

分庫分表模式下需要應用設計之初就要明確各表的拆分鍵、拆分方式(range、取模、一致性雜湊或者自定義路由表)、路由規則、拆分庫表數量、擴容方式等。相比NewSQL資料庫,這種模式給應用帶來了很大侵入和複雜度,這對大多數系統來說也是一大挑戰。

分庫分表模式也能做到線上擴容,基本思路是透過非同步複製先追加資料,然後設定只讀完成路由切換,最後放開寫操作,當然這些需要中介軟體與資料庫端配合一起才能完成。

這裡有個問題是NewSQL資料庫統一的內建分片策略(例如tidb基於range)可能並不是最高效的,因為與領域模型中的劃分要素並不一致,這導致的後果是很多交易會產生分散式事務。 舉個例子,銀行核心業務系統是以客戶為維度,也就是說客戶表、該客戶的賬戶表、流水錶在絕大部分場景下是一起寫的,但如果按照各表主鍵range進行分片,這個交易並不能在一個分片上完成,這在高頻OLTP系統中會帶來效能問題。

分散式SQL支援

常見的單分片SQL,這兩者都能很好支援。NewSQL資料庫由於定位與目標是一個通用的資料庫,所以支援的SQL會更完整,包括跨分片的join、聚合等複雜SQL。中介軟體模式多面嚮應用需求設計,不過大部分也支援帶拆分鍵SQL、庫表遍歷、單庫join、聚合、排序、分頁等。但對跨庫的join以及聚合支援就不夠了。

NewSQL資料庫一般並不支援儲存過程、檢視、外來鍵等功能,而中介軟體模式底層就是傳統關聯式資料庫,這些功能如果只是涉及單庫是比較容易支援的。

NewSQL資料庫往往選擇相容MySQL或者PostgreSQL協議,所以SQL支援僅侷限於這兩種,中介軟體例如驅動模式往往只需做簡單的SQL解析、計算路由、SQL重寫,所以可以支援更多種類的資料庫SQL。

SQL支援的差異主要在於分散式SQL執行計劃生成器,由於NewSQL資料庫具有底層資料的分佈、統計資訊,因此可以做CBO,生成的執行計劃效率更高,而中介軟體模式下沒有這些資訊,往往只能基於規則RBO(Rule-Based-Opimization),這也是為什麼中介軟體模式一般並不支援跨庫join,因為實現了效率也往往並不高,還不如交給應用去做。

這裡也可以看出中介軟體+分庫分表模式的架構風格體現出的是一種妥協、平衡,它是一個面向應用型的設計;而NewSQL資料庫則要求更高、“大包大攬”,它是一個通用底層技術軟體,因此後者的複雜度、技術門檻也高很多。

儲存引擎

傳統關聯式資料庫的儲存引擎設計都是面向磁碟的,大多都基於B+樹。B+樹透過降低樹的高度減少隨機讀、進而減少磁碟尋道次數,提高讀的效能,但大量的隨機寫會導致樹的分裂,從而帶來隨機寫,導致寫效能下降。

NewSQL的底層儲存引擎則多采用LSM,相比B+樹LSM將對磁碟的隨機寫變成順序寫,大大提高了寫的效能。不過LSM的的讀由於需要合併資料效能比B+樹差,一般來說LSM更適合應在寫大於讀的場景。當然這只是單純資料結構角度的對比,在資料庫實際實現時還會透過SSD、緩衝、bloom filter等方式最佳化讀寫效能,所以讀效能基本不會下降太多。NewSQL資料由於多副本、分散式事務等開銷,相比單機關聯式資料庫SQL的響應時間並不佔優,但由於叢集的彈性擴充套件,整體QPS提升還是很明顯的,這也是NewSQL資料庫廠商說分散式資料庫更看重的是吞吐,而不是單筆SQL響應時間的原因。

成熟度與生態

分散式資料庫是個新型通用底層軟體,準確的衡量與評價需要一個多維度的測試模型,需包括髮展現狀、使用情況、社群生態、監控運維、周邊配套工具、功能滿足度、DBA人才、SQL相容性、效能測試、高可用測試、線上擴容、分散式事務、隔離級別、線上DDL等等。雖然NewSQL資料庫發展經過了一定時間檢驗,但多集中在網際網路以及傳統企業非核心交易系統中,目前還處於快速迭代、規模使用不斷最佳化完善的階段。

相比而言,傳統關聯式資料庫則經過了多年的發展,透過完整的評測,在成熟度、功能、效能、周邊生態、風險把控、相關人才積累等多方面都具有明顯優勢,同時對已建系統的相容性也更好。

對於網際網路公司,資料量的增長壓力以及追求新技術的基因會更傾向於嘗試NewSQL資料庫,不用再考慮庫表拆分、應用改造、擴容、事務一致性等問題怎麼看都是非常吸引人的方案。對於傳統企業例如銀行這種風險意識較高的行業來說,NewSQL資料庫則可能在未來一段時間內仍處於探索、審慎試點的階段。基於中介軟體+分庫分表模式架構簡單,技術門檻更低,雖然沒有NewSQL資料庫功能全面,但大部分場景最核心的訴求也就是拆分後SQL的正確路由,而此功能中介軟體模式應對還是綽綽有餘的,可以說在大多數OLTP場景是夠用的。

限於篇幅,其它特性例如線上DDL、資料遷移、運維工具等特性就不在本文展開對比。

總結

如果看完以上內容,您還不知道選哪種模式,那麼結合以下幾個問題,先思考下NewSQL資料庫解決的點對於自身是不是真正的痛點:

  • 強一致事務是否必須在資料庫層解決?
  • 資料的增長速度是否不可預估的?
  • 擴容的頻率是否已超出了自身運維能力?
  • 相比響應時間更看重吞吐?
  • 是否必須做到對應用完全透明?
  • 是否有熟悉NewSQL資料庫的DBA團隊?

如果以上有2到3個是肯定的,那麼你可以考慮用NewSQL資料庫了,雖然前期可能需要一定的學習成本,但它是資料庫的發展方向,未來收益也會更高,尤其是網際網路行業,隨著資料量的突飛猛進,分庫分錶帶來的痛苦會與日俱增。當然選擇NewSQL資料庫你也要做好承擔一定風險的準備。

如果你還未做出抉擇,不妨再想想下面幾個問題:

  • 最終一致性是否可以滿足實際場景?
  • 資料未來幾年的總量是否可以預估?
  • 擴容、DDL等操作是否有系統維護視窗?
  • 對響應時間是否比吞吐更敏感?
  • 是否需要相容已有的關聯式資料庫系統?
  • 是否已有傳統資料庫DBA人才的積累?
  • 是否可容忍分庫分表對應用的侵入?

如果這些問題有多數是肯定的,那還是分庫分表吧。在軟體領域很少有完美的解決方案,NewSQL資料庫也不是資料分散式架構的銀彈。相比而言分庫分表是一個代價更低、風險更小的方案,它最大程度複用傳統關聯式資料庫生態,透過中介軟體也可以滿足分庫分表後的絕大多數功能,定製化能力更強。在當前NewSQL資料庫還未完全成熟的階段,分庫分表可以說是一個上限低但下限高的方案,尤其傳統行業的核心繫統,如果你仍然打算把資料庫當做一個黑盒產品來用,踏踏實實用好分庫分表會被認為是個穩妥的選擇。

參考資料

[1]

pavlo-newsql-sigmodrec:

[2]

為什麼大部分NoSQL不提供分散式事務?:

[3]

Spanner, TrueTime 和CAP理論:

[4]

站在巨人的分散式肩膀上:


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

相關文章