打造一款強大成熟的資料庫有多難?

語言: CN / TW / HK

作者:康凱森,StarRocks PMC,負責查詢方向的研發(本文轉自其個人部落格“程式設計小夢”)

從 2015 年開始,我在美團先後維護和研發過 Apache HBase、Apache Kylin、Apache Druid 和 Apache Doris,對大資料系統和 OLAP 資料庫有了深入理解。

2020 年開始,我加入了 StarRocks 社群。我們先後打造了業界領先的向量化執行器、CBO 優化器、Pipeline 並行引擎、支援高效 Update 的儲存引擎和極速資料湖分析。支援儲存分離的 Cloud Native 版本也即將面世。

一路走來,隨著 StarRocks 專案攻克一個又一個技術難題,解決一個又一個使用者需求和難題,服務著越來越多的使用者,我對如何打造一個強大且成熟的資料庫有了更深的理解。在這篇文章中,我會和大家介紹打造一個強大且成熟的資料庫都有哪些難點。

 

#01

本質矛盾

 

無論是一個年輕的社群團隊,還是一家大公司的資料庫部門,打造一款強大且成熟的資料庫都會有下面兩個本質矛盾:

有限人力和無限工作之間的矛盾

各種各樣的使用者需求,無止境的效能優化,永遠也修不完的 Bug,一個又一個 Killer Feature 的打造,時刻不停的程式碼重構,增加不完的測試 Case,不間斷的技術調研和系統設計。這些工作都需要大量人力,但無論哪家公司,人力總是不足的,優秀的資料庫人才更是稀缺。

飛速增長與成熟穩定的矛盾

如果資料庫的程式碼不大變,面對的應用場景不大變,我們讓一個數據庫變穩定會容易很多。但是如果一個數據庫的程式碼在飛速變化和增長,應對的應用場景不斷豐富和變化,讓一個數據庫穩定下來就會很難。

 

#02

定位和獨特性之難

 

一款資料庫想要在產品和商業上取得成功,想在很多競品中脫穎而出,就必須有清晰的定位和自己的獨特性。一款資料庫的獨特性就是自己的價值點,比如目前 StarRocks 的價值點就是極速統一。

一旦定位和獨特性定義清楚,便意味著產研資源重心和方向的傾斜。而一款資料庫想要讓自己的獨特性成為 Killer Feature,就必須超越所有競品。這就意味著,這個資料庫團隊必須有足夠強大的創新能力,足夠強大的工程能力,才能做到其他資料庫公司一定時間內無法做到的。

 

#03

架構之難

 

一個數據庫的架構決定了一個數據庫未來的上限,決定了一個數據庫未來支援更多使用者需求的難易程度。如果架構設計有誤,後面的很多功能和優化成本就會很高,甚至無法實現。不過在當下,雲時代資料庫的架構逐漸趨同,想要有足夠的獨特性和明顯的優勢還是比較困難。

 

#04

功能之難

 

Killer Feature 的創新性和獨特性

一般資料庫在產品功能上肯定會推出幾個 Killer Feature,作為自己產品的賣點。但是想作為 Killer Feature,就必須比競品好很多,這時候 Killer Feature 就必須擁有一定的創新性和獨特性。

持續不斷的使用者需求

使用者越來越多,使用者的需求自然就會越多,有些使用者的需求很小眾。但有時候為了服務一個使用者,我們卻不得不做,而且有時候做了還會給系統帶來額外的複雜性。

各種各樣的認證

認證裡面的一些功能其實並不是你的資料庫產品所必須的,做了不會明顯增加產品競爭力。為了滿足並獲取更多企業級使用者,還是得投入大量人力去通過認證。

使用者遷移時的功能對齊

當一個新系統越來越好,要擴大市場規模,必然要去替換使用者已有的舊資料庫,但是替換過程中經常會遇到語法、函式、功能不對齊的場景。這時候,如果這個使用者很重要,你就不得不去做一些和傳統資料庫功能對齊的事情。

系統越強大會越複雜

  • 越強大的優化可能跨模組越多:比如 StarRocks 的低基數優化和匯入、查詢、Delete、Update、Compaction、Schema Change、 MVCC 等很多模組都有關係,所以這類功能的測試本身就會很複雜

  • 一個新的功能或者優化可能會打破舊的功能或者優化的假設:比如 Tablet 並行可能和 Local exchange 有衝突,比如 Query Cache 可能和 Shared Scan 有衝突

系統越成熟,新的功能和優化要求越高,大規模使用週期越長

  • 新系統的第一個版本往往會給使用者建立一個 Baseline,之後的版本做的功能和優化就必須考慮所有使用者的場景,在自己的使用者場景下沒有或者很少有 Bad Case

  • 使用者使用一個系統穩定後,升級的動力會越來越弱,所以越靠後的版本得到使用者大規模驗證的週期也會更長

 

#05

效能之難

 

CBO 優化器 Plan 的穩定性和正確性

  • 統計資訊的變化會導致查詢 Plan 發生劇變

  • 某些優化就是會導致部分查詢變快, 部分查詢變慢

  • 選擇度估計和基數估計一般都假設了資料的均勻分佈,但這和實際情況並不相符

  • 統計資訊收集如何做到相對準確又不耗費大量的系統資源

單核效能優化

單核效能優化是一個沒有止境的過程,我在 StarRocks 技術內幕:向量化程式設計精髓 一文中已經解釋了單核優化的關鍵點和方法論,所有運算元和函式的深度優化是需要數十人年的事情。

多核擴充套件性優化

StarRocks 單核效能登頂 ClickBench 後,我們在優化多核效能上投入了大量精力。相比單核,突破多核擴充套件性的瓶頸要更困難些,目前已經做了大量優化、還遠遠不夠。不同型別的查詢在高併發下會遇到不同的瓶頸:Lock,執行緒池,RPC,排程問題,NUMA,CPU Cache,記憶體管理,IO 非同步等。

多機擴充套件性優化

多機的擴充套件性的常見瓶頸點主要包括:

  • RPC 的擴充套件性

  • 元資料的擴充套件性

  • 如何解決資料傾斜

  • 如何通過排程策略解決熱點,充分呼叫整個叢集的算力

  • 優化器要確保每個運算元,函式都可以生成分散式的執行計劃,不會有單點執行的瓶頸

儲存引擎的優化

儲存引擎需要在匯入效能和查詢效能之間進行權衡,一般情況下,匯入時候做的事情越多,查詢時候的代價就更低些:

  • 更新能力的持續優化

  • 匯入能力的持續優化

  • 壓縮和編碼

  • Compaction 策略的持續優化

  • 事務能力的優化

  • 記憶體使用上的優化

  • 各個級別 Cache 能力的優化

針對特定場景的效能優化一般會增加系統複雜性

資料庫一般都是面向通用場景開發,但是在特定場景下可以獲取更多資訊和上下文,這時就可以進行更多的針對性優化。但這樣也會帶來問題,比如系統的程式碼邏輯更加複雜,測試和維護的難度更高。

如何保證效能不退化

當系統複雜之後,多人協作經常會出現的問題是,一個人之前精心寫的一段對效能影響很大的程式碼,被後人不小心改掉了。或者是優化 A 優化了某些場景的效能,但是卻導致之前優化 B 的優化失效了。

如何能 Cover 不同的硬體環境

資料庫這個複雜的軟體是構建在硬體之上的,硬體是決定效能的基礎。但是 CPU 有不同的型號,網路頻寬有高有低,磁碟的吞吐和 IOPS 也有很大的差別,有可能一些軟體層面的優化只對某些硬體環境生效。

 

#06

穩定性之難

 

一款資料庫的成熟,主要體現在穩定性上,而打造一個穩定的資料庫有如下難點:

SQL 是宣告式的

  • 機器可以生成成千上萬行的 SQL,SQL 各種運算元和函式的組合是無法窮盡的,要保證任何一條 SQL 沒有 bug,是極其困難的

  • SQL 裡面的 Null 和 Nullable 是比較令人煩惱的,不僅對效能有很大影響,對正確性也有較大影響

成百上千的使用者場景

每個使用者的硬體配置,環境資訊,應用特點不一樣,都可能引發不同的問題。

各種各樣的叢集規模

很多時候,只有當叢集規模、資料量、併發量到一定程度,一些穩定性和擴充套件性的問題才會暴露出來。如何在產品釋出之前,在有限的資源下,通過測試暴露這些問題也是一個難點。

功能的組合

很多時候,一個功能單獨 Work 沒有問題,但是多個功能相互影響時,一些 Bug 才會暴露出來。比如節點下線,觸發資料的均衡和複製,又會觸發資料版本的問題,進而觸發查詢的問題。比如匯入、查詢、Compaction、系統任務對 IO 資源的共同影響,這些複雜功能組合時的測試難度會更大。

函式的預期行為沒有標準

比如 Date 型別和數字的比較,字串和數字的比較,應該是直接報錯還是隱式轉換,隱式轉換的公共型別轉成啥。這些其實都沒有統一的標準,每個資料庫都有自己的實現。關鍵問題是即使改成最合理的表現,一些使用者可能會因為習慣自己熟悉的資料庫的表現,覺得當時最合理的表現是不合理的。

還有聚合函式溢位後行為,Decimal 運算精度的確定,函式一些異常行為是拋異常還是轉 Null。我們不僅要相容使用者期望的行為和正確性,還要兼顧正確性和效能。

多版本維護

由於快速迭代和發展,我們必然要維護很多版本,這給穩定性提出了更大的挑戰:

  1. 定位,復現問題成本會更高,比如研發得用指定版本的程式碼部署環境,復現問題

  2. 解決問題後,也必須給所有版本 Cherry-pick,這時候很容易遺漏某個版本

  3. 要確定某個 Bug 到底在哪些版本修復了,成本也比較高

  4. 某個版本發生大的改動或者重構,之後的 Bug Fix PR Cherry-pick 就無法自動化,人工操作的成本會很高

相容性問題

當我們維護很多個版本後,有時候不得不做一些不相容的改動:

  1. 之前的行為本身是錯誤的或者不合理的

  2. 想完全刪除某些舊程式碼

查詢層是無狀態的,所以不相容的改動一般可以繞過或改 SQL 解決。但是儲存層和元資料層是有狀態的,一旦有不相容的問題會很麻煩。

不同語言的行為不一致

對於類似 StarRocks 這種多程序、多語言的資料庫,在穩定性問題上還有一個額外的挑戰是:

  • 不同語言的一些標準庫行為會不一樣,這會導致在不同模組計算相同函式的結果不一致

  • 之前遇到不同語言 Java 和 C++ 取餘的結果不一致

這幾年來,我遇到過挺多這樣的 Case。

編譯器的 Bug

一般編譯器被各種專案大量使用,我們開發者遇到 Bug 的機會比較少。

不過在開發 StarRocks 向量化的過程中,我就遇到了一個編譯器的 Bug:編譯器進行向量化優化後,把 Boolean 值轉成了 255:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97255

還有最近遇到的一個 C++ 正則標準庫的 Bug:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164#c8

分散式相關問題

現在的資料庫幾乎都是分散式資料庫,所以分散式系統遇到的問題,一般資料庫都會遇到。比如分散式系統的常見挑戰:單點故障,部分失敗,不可靠的網路,不可靠的時鐘。

硬體故障

資料庫的儲存引擎必須保證資料能被正確地儲存和讀取,但是我們在實際環境中不可避免會遇到各種硬體故障:磁碟壞掉,磁碟資料錯誤,伺服器宕機,機房斷電,網路異常等。

 

#07

生態之難

 

資料匯入

  • 資料格式的多樣性:CSV,JSON,Parquet,ORC,ARROW 等

  • 資料來源的多樣性:Local File,Kafka,Hive,資料湖,傳統資料庫等

  • 匯入時支援 Transform (表示式計算)

資料匯出

  • 匯出格式的多樣性

  • 匯出位置的多樣性:客戶端,本地,分散式儲存等

  • 全量匯出和部分匯出

BI 工具:資料視覺化

市面上流行的 BI 工具多達幾十種,每種 BI 工具深入使用後都或多或少會有些相容性問題:Session 變數的相容性,資料型別的相容性,函式的相容性等。要儘可能完美地相容,必然有大量的人力投入。

資料遷移

要支援使用者從傳統資料庫和各種競品資料庫順滑遷移,就必須和各種資料庫進行對接,這裡面有大量瑣碎的工作。

比如我們想將 Presto 的使用者遷移到 StarRocks 上,我們就需要在 SQL 語法層進行相容。

比如單機資料庫上一些很容易實現的功能,在分散式資料庫上就會相對困難,這時候如果為了功能對齊,就需要不少的工作。

 

#08

安全之難

 

安全包括:認證,鑑權,審計,加密,脫敏等。這裡面每一項都有著大量的工作,對於金融、政府客戶、安全體系要求很高,公有云上的安全要求則會更高。

 

#09

易用性之難

 

在未來,毋容置疑,易用性會越來越重要,並將會是一款資料庫的核心競爭力。資料庫分析師需要知道的資料庫知識會越來越少,需要進行的操作會越來越少。易用性主要體現在 3 個層次:

  1. 架構層面的易用性:比如自適應執行,Automatic Clustering,Automatic Index,Automatic Scale 等。

  2. 產品層面的易用性:比如介面定義和功能上是不是足夠簡潔清晰,一個命令可以匯入各種資料來源,各種資料格式的檔案,一個命令可以查詢各種資料來源、檔案等。

  3. 細節層面的易用性:文件是否完善,報錯資訊是否清晰易懂,可觀測性是否足夠好。

 

#10

難點如何解決

 

在你將這些點一個一個深入思考下去,肯定會理解打造一個強大且成熟的資料庫是多麼困難,那麼這些難題如何解呢?

歡迎關注 StarRocks 微信公眾號,後續我們繼續探討、揭祕!

 

關於 StarRocks 

面世兩年多來,StarRocks 一直專注打造世界頂級的新一代極速全場景 MPP 資料庫,幫助企業建立“極速統一”的資料分析新正規化,助力企業全面數字化經營。

當前已經幫助騰訊、攜程、順豐、Airbnb 、滴滴、京東、眾安保險等超過 170 家大型使用者構建了全新的資料分析能力,生產環境中穩定執行的 StarRocks 伺服器數目達數千臺。 

2021 年 9 月,StarRocks 原始碼開放,在 GitHub 上的星數已超 3600 個。StarRocks的全球社群飛速成長,至今已有超 200 位貢獻者,社群使用者近萬人,吸引幾十家國內外行業頭部企業參與共建。