刪除 27 萬行 C++ 代碼,轉用 Rust 重寫數據庫,真的值得嗎?
摘要:團隊用 7 個月寫了 27 萬行 C++ 代碼,為什么突然要用 Rust 重寫,來看數據庫創業公司 RisingWave Labs 創始人兼首席執行官吳英駿博士的現身說法。
鏈接:https://medium.com/@Aaron0928/the-founder-of-the-database-rewrite-with-rust-is-back-was-it-worth-deleting-270-000-lines-of-c-46a8713bd8e6
聲明:本文為 CSDN 翻譯,未經允許禁止轉載。
前段時間,數據庫創業公司 RisingWave Labs 發表博文,宣布徹底刪除RisingWave(該公司的云原生流數據庫)的 27 萬行 C++ 代碼,并用 Rust 語言重寫。
為此,我們采訪了該公司的創始人兼首席執行官吳英駿博士,詳細探討了重寫的前中后期準備工作、遇到的問題以及經驗教訓。
放棄 Rust,最初的選擇是 C++
提問:選擇哪種編程語言與 RisingWave 的功能有關系嗎?
吳英駿:RisingWave 是一款云原生流式數據庫,主要服務于需要超低延遲實時的數據分析應用。其定位不僅是一個 SQL 數據庫系統,還提供流處理能力:使用流數據執行連續查詢,并以物化視圖的形式動態維護結果。另外,RisingWave 采用了分層架構,建立在現代云基礎設施之上,利用云資源為用戶提供成本和性能的細粒度控制。
這個架構最大的特點在于,資源是無限的。由于有無限的資源,性能就不會成為特別大的問題——只要添加資源,性能就能提到提升。但資源是收費的,設備也是收費的,我們希望能在保證用戶性能的前提下,降低整個系統的成本,讓普通用戶以較為低廉的價格使用我們的服務,這也是我們的核心設計理念。
這與編程語言的選擇沒有太大關系,開發一款數據庫可以使用各種各樣的語言,比如 C++、Rust、Java,Scala 等,一些交易系統可能還會考慮 Haskell。不過即便是二十年前,也很少有人用 Java 、Basic、Python 這類語言構建數據庫,主要因為這些語言的運行效率和性能均不高。
因此,我們主要希望選擇一門高性能的編程語言,而所謂的高性能語言不外乎 C++、Rust 或者一些小眾語言,如果又想被用戶廣泛接受,那基本上就是 C++ 和 Rust。
提問:據了解,你們團隊最初選擇的是 C++,還集結了多位擁有 10 年以上經驗的 C++ 工程師。當初你們是看中了 C++ 的哪些特質,還是說你們只是遵從了市場上大部分數據庫系統的選擇?
吳英駿:我本人比較擅長 C++,不管是讀博期間還是創業之前開發的所有數據庫都是用 C++ 編寫的,我沒有用其他任何語言寫過項目。
創業之初,有人提議使用 Rust,理由是 Rust 很火。但在我看來,這算不上一個充分理由,我們又不是想成為網紅,選擇一門語言不能僅僅是為了火,我們需要考慮哪種語言適合團隊,以及數據庫領域的通用語言是什么。在數據庫領域,雖然 TiDB 的存儲引擎 TiKV 是用 Rust 寫的,但這不足以證明用 Rust 寫的數據庫系統都能成功,相反絕大多數成功的數據庫系統都是用 C++ 編寫的。
從招聘的角度來看,我們肯定希望招募到數據庫領域的專家,而擁有多年數據庫領域經驗的專家大多來自如今的主流數據庫提供商——這些數據庫也基本都是用 C++ 寫的。
相較而言,Rust 是一門比較年輕的語言,缺少重量級項目。盡管實際上很多項目都使用了Rust,其中一些還是相對流行的項目,但還算不上重量級的大工程,生態系統或多或少有些不足。
綜上,最終我們決定使用 C++ 作為主要開發語言。
選擇用 Rust 重寫
提問:你們團隊已經在這個項目上投入了 7 個多月,你也提到時間對于創業公司而言是非常寶貴的,是因為什么契機讓你們覺得不重寫不行了?
吳英駿:首先,C++ 比較常見的問題是內存泄漏,但這類 Bug 比較容易修復,我們覺得可以忍。其次,依賴管理很痛苦,雖然 CMake 工具可以自動配置 C++ 項目的編譯,但使用起來還是很麻煩,我們仍然需要手動配置并安裝依賴庫;STL 庫缺乏對一些現代編程工具的支持,依賴的社區項目大多數還缺乏長期支持。最后,我們招聘到的成員 C++ 水平參差不棄,每個人都有自己的風格,非常難以統一,導致閱讀代碼的難度過大,審查代碼更是勞心勞力。隨著越來越多人員的加入,C++ 問題暴露得越來越頻繁,在此期間不斷有工程師提出是否可以考慮用 Rust 重寫。
另外,流式數據庫通常用于處理對延遲非常敏感的關鍵性任務。因此,構建 RisingWave 的編程語言必須滿足以下要求:保證零成本抽象,不能有性能上限;不需要運行時垃圾收集,可以控制由內存管理引起的延遲峰值。
起初,我們并不想更換語言,畢竟已經寫了這么久。但最終我們決定,如果支持用 Rust 重寫的工程師可以成功重寫一個獨立的模塊,我們就考慮重寫整個數據庫。與此同時,我也想起之前在 AWS Redshift 工作中遇到的一個 Bug,三個人不斷調試了兩周都無解,最終發現是內存泄漏的問題。如果現在項目繼續下去很可能也會遇到類似的情景,假設那時產品已經有了很多用戶,我們還需要因為這種內存泄露的問題調試許久,那就得不償失了。所以就在那個時候,我們開始認真考慮是否要用 Rust 重寫。
經過慎重評估,我們需要花費大約兩個月的時間就可以用 Rust 重寫原來七個月寫的代碼,這個時間差主要是由于項目的邏輯框架已在項目前期梳理清楚。暑假期間公司招了大量實習生,人手比較充足,且很多實習生都有 Rust 的基礎,這些都提升了重寫的速度。最后,經過全公司的表決投票,我們開始重寫。
在替換的過程中,我們選擇逐個模塊替換,這也保證了整個過程不會出現很嚴重的問題。
提問:用 Rust 重寫以后,C++ 代碼風格不統一的問題得到解決了嗎?
吳英駿:風格不統一的問題肯定不是用 Rust 就能解決的,但相對 C++ 會有很大程度的改善。C++ 中關于指針等的寫法很難統一,還容易造成安全性的問題。
提問:C++ 中一些語言層面的缺陷由來已久,在使用 C++ 作為主要開發語言之前,你沒有遇到過上述問題嗎?
吳英駿:我之前也遇到過,但在我上學期間,Rust 還不完善,用戶很少,因此不會考慮到用 Rust 去開發數據庫。此外,我之前接觸的數據庫都是比較成熟的產品,比如 IBM DB2,所以我的大部分工作時間都在調試,很難有精力和時間去重寫一個誕生于幾十年前的數據庫。
在大型企業內部,只有不太重要的項目或者用戶數量不多的項目才有可能被重寫,否則就需要投入大量的精力和資源。對于起步階段的創業公司來說,還是有機會重寫的,一旦面對客戶交付的壓力,重寫就不太可能了。
提問:在重寫之前,系統已經完成了多少?
吳英駿:簡單來說,框架已是比較清晰的水平。重寫不至于發現之前的 Bug,但通過重寫,我們確實會考量各個部分設計的合理性。
Rust 的優勢
提問:Rust 有哪些有優勢?
吳英駿:首先,安全性絕對是一大優勢,這對數據庫項目非常重要。其次,包管理需要的工作量非常少,C++ 有非常多的庫,包管理非常復雜,你需要花費幾個小時才能搞清楚如何在 CMake 里面配置一個包管理工具,即便在配置之后也需要花費很多時間,比如無法安裝,還可能遇到重名的問題(其他項目中使用的變量名稱與我們庫中的名字重合了),這些問題都需要手動解決,而且改起來費時費力。
重寫的收益
提問:重寫前后的收益情況如何?
吳英駿:一句話總結:收益巨大。從收益比的角度看,我們損失的是時間,因為分段重寫大概花費了一個月左右,但這些時間并沒有白白浪費,這個過程讓我們又反思了一遍不同模塊的設計思路,改掉了其中不合理的部分。對數據庫系統而言,這是一個長周期的項目,早期孵化階段時間的寶貴程度和正式上線后肯定是有區別的。當對象是直接用戶時,數據庫系統出現任何問題都是不能忍的。
我們收獲的是系統更加穩定、安全,且代碼清晰,尤其是包管理部分有非常大的提升。此外,Rust 本身在高速發展中,整個社區非常有活力,提問基本都能夠得到及時回復,這是 Rust 生態系統帶給我們的優勢。
使用 Rust 重寫代碼的注意事項
提問:重寫之后,原來那批 C++ 工程師都自學了 Rust 嗎?
吳英駿:團隊中的部分工程師之前就掌握了 Rust,只是未在工作中使用,這部分工程師還是比較容易轉換的。我們也專門讓一些工程師評估從零開始學 Rust 需要多久,絕大多數工程師基本能夠在一個月之內掌握 Rust,但還達不到全面掌握,只是可以使用 Rust 寫一些代碼。
整個過程比較順利,因為部分工程師會利用業余時間自學 Rust,并將經驗傳播給其他人,這是非常重要的。我認為,如果公司決定重寫,那么公司內部必須有一到兩位,甚至更多位擁有 Rust 實戰經驗的工程師,或者至少愿意利用業余時間學習,并將經驗傳授給其他人,這可以降低整個公司的學習難度,畢竟 Rust 的學習曲線是比較陡峭的。
提問:擁有其他編程語言基礎對于學習 Rust 有影響嗎?
吳英駿:會有差異,而且比較明顯。對于其他語言,比如 Python,最大的特點是簡化編程,開發人員不需要考慮內存管理等問題,但 Rust 需要這方面的基礎,所以擁有不同的語言背景,對于學習 Rust 的成本有不同的影響。
提問:Rust 一直存在編譯時的問題,你們有感受到嗎?
吳英駿:Rust 確實存在編譯時問題,但 C++ 的編譯相對也很慢,所以目前還可以忍受。如果編譯時間過長,工程師會定期查看編譯過程,并嘗試是否有辦法可以縮短這個時間。
提問:你會建議什么類型的公司或者業務團隊在什么情況下選擇重寫代碼庫?
吳英駿:如果是大型公司內部選擇重寫,大概率表明項目本身不是那么重要,或者是核心項目的邊緣模塊,用戶沒有那么多、公司又有錢、有資源、有人力,這種情況下可以考慮重寫。對于創業公司而言,早期還有精力重寫,一旦用戶量上來就會面臨交付壓力,基本不太會做這種決定。
此外,你需要搞清楚換編程語言的理由,出于性能、安全性或者其他原因,而不只是因為某種語言很火。以數據庫領域為例,現在很多成功的數據庫誕生距今已有十年以上,經歷了長時間的磨煉,其實轉 Rust 的需求并不大。總的來說,我認為考慮實際的需求非常重要,你需要綜合考慮再做決定。
提問:你覺得目前 Rust 的生態環境如何?
吳英駿:整體來看 Rust 的生態環境比較不錯,主要問題在于缺少大型項目驗證,比如 Go 最成功的項目是 Kubernetes。但我們也看到不少科技公司考慮使用 Rust 重寫某些服務,比如 InnoDB,也看到很多公司加入了 Rust 基金會,比如 AWS、Google、Facebook 等。我相信,有了這些公司的長期支持,未來會出現一些非常不錯的項目,Rust 會變得越來越好。
提問:選擇用 Rust 重寫與團隊規模和狀態之間是否有關系?
吳英駿:我覺得重寫和團隊規模的關系不是很大,但我更建議年輕的團隊選擇 Rust,當然這也因人而異。至于最終是否要轉,也要考慮團隊大多數人的意見,因為在學習了一段時間之后,發現還是沒有熟練掌握 Rust 可能會有很強的挫敗感,這需要團隊成員的共同努力,僅憑興趣很難做好。此外,僅憑興趣決定創業以及對外提供商業化服務,這也是非常不負責的。
本文來自微信公眾號“CSDN”(ID:CSDNnews),36氪經授權發布。
