沒有完美的分散式架構

qing_yun 發表於 2022-07-08

這是“沒有完美”系列的第三篇,以前我寫過《沒有完美的資料庫》,《沒有完美的儲存引擎》,今天我們來聊聊目前最為熱門的分佈資料庫架構。大家要注意今天我們討論的不是分散式資料庫本身,而是分散式資料庫架構。分散式資料庫太複雜了,也太多了,要想簡單分析一下夠一篇萬字長文了,今天我們重點來分析一些目前最常見的國產分散式資料庫架構,即使縮小到這個話題,實際上也是十分複雜的,我們今天只做一些粗略的分析。如果有朋友覺得這篇文章還算有點價值,並且對其中某些點希望進一步分析,請留言通知,我找時間寫一些。

這篇文章是今天早上在上班路上開始思考的,7點20進入辦公室開始寫,8點40寫完,只用了一個多小時,因此難免一些觀點有些考慮不周,請讀者見諒了。

現今國產分散式資料庫市場十分熱鬧,僅僅是交易型關係型資料庫就有近百款,大家在選擇資料庫的時候也容易挑花了眼。以前我也寫文章討論過,沒有完美的資料庫,使用者應該根據其場景和應用需求來選擇合適自己的資料庫產品。資料庫架構也是其中的一個重要的選擇要素,特別是分散式資料庫,不同的架構其優缺點十分明顯,某些分散式資料庫存在的缺陷因為架構問題,是較難解決的,因此瞭解某個分散式資料庫屬於哪種架構,有哪些優點和缺點十分重要。

分散式資料計算最主要有兩種形式,一種是分割槽SHARDING,一種是全域性一致性HASH,根據這種分散式資料計算的種類不同,衍生出存算分離和存算一體這兩種分散式資料庫架構。進一步再分出一系列子類別,比如對等模式,代理模式,外掛模式等。

存算一體SHARDING模式的分散式資料庫最為典型的是Oceanbase。下面是OB的架構圖:

沒有完美的分散式架構

每個Observer是一個計算儲存一體化的獨立服務,帶有SQL引擎,事務引擎和儲存引擎,並儲存一部分分片資料(分割槽)。OB採用的是對等模式,客戶端連線到任何一個OBSERVER都可以全功能使用資料庫。OBSERVER會自動產生分散式執行計劃,並將運算元分發到其他參與協同計算的OBSERVER上,完成分散式計算。管理整個叢集的RootService只在部分Observer中存在,並全域性只有一個是主的,其他都是備的。實際上每個OBSERVER就組成了一個完整的資料庫,如果所有的資料都儲存於一個OBSERVER上,我們的訪問方式類似於一個集中式資料庫。

這種架構下的資料分割槽採用了高可用,一個資料寫入主副本(Leader)後會自動同步到N個備副本,OB採用Paxos分割槽選舉演算法來實現高可用。其備副本可以用於只讀或者弱一致性讀(當副本資料存在延遲時),從而更為充分的利用多副本的資源。實際上不同的分佈資料庫的主備副本的使用方式存在較大的差異,有些分散式資料庫的備副本平時是不能提供讀寫的,只能用於高可用。

大家看到這裡,可能覺得OB的架構不錯,各種問題都考慮得比較周到了。不過還是那句話,沒有完美的分散式資料庫架構,SHARDING儲存需要分佈在各個SHARDING分割槽中的分割槽表要有一個SHARDING KEY,根據SHARDING KEY來做分片處理。SHARDING模式雖然應對一般的資料庫操作是沒問題了,不過如果一條複雜的查詢語句中沒有關於SHARDING KEY,那麼就沒辦法根據SHARDING KEY去做分割槽裁剪,必須把這個運算元分發到叢集中儲存這張表的分割槽的所有OBSERVER上,這種情況被稱為SHARDING資料庫的讀放大。

採用SHARDING模式的資料庫系統,你要區分其技術水平,重點要看針對讀放大的措施是否完善,你的應用系統能否採用這些方案來讓讀放大的影響變得更小。實際上OB在這方面做了不少工作,今天篇幅問題,我們不展開討論了。

既然存算一體的SHARDING模式有這種缺陷,那麼能不能採用存算分離的方案呢?大家來看TIDB的架構:

沒有完美的分散式架構

TIDB是採用存算分離的,計算引擎TIDB和儲存引擎TIKV是分離的,因此TIDB不存在存算一體的SHARDING分散式資料庫的這種讀放大的問題。似乎TIDB要技高一籌,完美地解決了OB等SHARDING資料庫的問題。不過事實上沒有那麼簡單,就像我上大學時的老師陳道蓄先生說過的“任何好東西都是有代價的”,存算分離解決了SHARDING的讀放大問題,但是又引入了一個新的問題。那就是計算節點的本地緩衝問題。因為大型分散式計算環境下實施緩衝區融合成本極高,因此每個TIDB節點只能有本地緩衝,不能有全域性緩衝。因此在TIDB的SQL引擎上是沒有全域性DB CACHE的,TIDB的資料緩衝只能建立在TIKV和TIFLASH上。SQL引擎->DB CACHE->儲存路徑->資料儲存介質這種傳統資料庫的資料讀取模式變成了SQL引擎->本地區域性緩衝->儲存路徑(網路)->儲存節點緩衝->儲存介質這種模式。其效率大大地降低了。為了解決這個問題,採用此類架構的資料庫系統,就必須採用更快的儲存介質,從而解決缺乏全域性DB CACHE支援的問題。當然這個問題也並不是不能解決的,通過更為細緻的運算元下推,採用類似ORACLE的SMART SCAN等技術,可以解決大部分問題。

實際上,國產分散式資料庫使用的最多的架構並不是上面的這兩種,而是基於SQL代理的存算分離架構,這種架構採用的資料儲存方式也是SHARDING方式,不過使用了一個SQL PROXY。騰訊TDSQL、熱璞HOTDB、中興通訊GOLDENDB、百度GAIADB、京東STARDB、openGauss分散式計算框架等著名分散式資料庫都是採用類似的架構。

沒有完美的分散式架構

TDSQL由排程器、閘道器、Agent三個核心元件加上MySQL組成,其中排程器是排程分散式計算的,內部又分為zookeeper和scheduler server;接入閘道器是一個SQL代理,應用連線到接入閘道器上進行SQL操作。代理與MySQL例項一起,構成資料節點。多個資料節點構成服務單元SET。每個SET是一組高可用組,由一主多備組成。資料按照SET進行SHARDING分割槽。

這種架構中的儲存引擎是一個完整的資料庫,大部分採用此類架構的分散式資料庫採用了MYSQL作為儲存引擎的核心,這是因為MYSQL管理起來比較輕量級,出問題大部分情況下隔離故障或者重啟例項就可以解決。這種架構在閘道器(代理)層就具有分散式計算的能力,在此層分解SQL,產生分散式執行計劃,然後將分解出的SQL分配給參與本次計算的所有儲存節點,儲存節點執行SQL,獲得所需要的資料集,傳輸給閘道器,由閘道器進行聚合計算。

這種架構的底層包含一個完整的資料庫引擎,因此可以把研發的主要精力放在閘道器SQL引擎上,大大降低了開發難度。不過雖然很多資料庫產品都是採用了此架構,各個廠商的技術能力不同,因此做出來的產品在效能,SQL支援能力等方面都存在較大的差距。儲存層採用完整的資料庫引擎也是個雙刃劍,如果不對資料庫引擎的優化器做大的優化,則資料庫引擎在效能上的弱點會帶壞整個分散式資料庫的效能,而去做優化又是大投入的工作。也是無法兩全其美的。

另外高可用方面的主從選擇,切主演算法的實現水平方面,也會影響此架構的資料庫的使用者使用體驗。最初此類架構的主從切換類似於MYSQL的主從切換,對前端應用的影響很大,如果業務高峰時出現主DN故障,那就是災難性的。現在一些頭部企業在這方面做了極大的優化,使用者體驗也得到了很大的改善。

還有一些分散式資料庫是採用SQL ON HADOOP架構的,比如易鯨捷。

沒有完美的分散式架構

其儲存引擎是一個經過了優化的HBASE相容的引擎,在此基礎上構建整個分散式資料庫系統。此種架構的優勢是底層採用了一個十分成熟的分散式儲存系統HDFS和分散式資料庫HBASE,天生對於大資料量的計算以及物聯網場景的應用有較好的支援。不過因為HADOOP本身並不是為低延時高併發的OLTP場景甚至HTAP場景設計的,因此儲存引擎很可能會成為今後資料庫的瓶頸。2017年我在貴州遇到時任易鯨捷cto的丁洪先生的時候,他也認為易鯨捷要脫胎換骨,必須重寫儲存引擎,使之更適合HTAP的應用場景。

時間關係,今天就聊到這裡了,似乎還是沒聊透。實際上就本文的標題“沒有完美的分散式資料庫架構”,我們的分散式資料庫架構好壞的爭論不妨放一放,大家都多一點考慮自身架構的缺點,想辦法去彌補自身的缺陷,那才是對使用者負責。

解決分散式計算的問題,在分散式SQL引擎優化,運算元下推,避免讀放大,主副本切換、讀寫分離、運維可觀測性提升等方面,都是需要認真去不斷提升的。選擇分散式資料庫,僅僅看架構是不夠的,更重要的是看資料庫廠商是不是針對我們的應用場景做了很好的優化,產品能否滿足我們應用場景的需求。


來自 “ 白鱔的洞穴 ”, 原文作者:白鱔;原文連結:https://mp.weixin.qq.com/s/8fZu8haRDWsqGxuubVLwaw,如有侵權,請聯絡管理員刪除。