勢高,則圍廣:TiDB 的架構演進哲學

勢高,則圍廣:TiDB 的架構演進哲學

本文來源 | PingCAP微信公眾號

作者 | PingCAP CEO劉奇,本文根據他在第 100 期 Infra Meetup 上的演講整理,預計閱讀時間為 30 分鐘,建議先收藏。

大家可能知道我是 PingCAP CEO,但是不知道的是,我也是 PingCAP 的產品經理,應該也是最大的產品經理,是對於產品重大特性具有一票否決權的人。中國有一類產品經理是這樣的,別人有的功能我們統統都要有,別人沒有的功能,我們也統統都要有,所以大家看到傳統的國內好多產品就是一個超級巨無霸,功能巨多、巨難用。所以我在 PingCAP 的一個重要職責是排除掉“看起來應該需要但實際上不需要”的那些功能,保證我們的產品足夠的專注、足夠聚焦,同時又具有足夠的彈性。

01最初的三個基本信念

本次分享題目是《TiDB 的架構演進哲學》,既然講哲學那肯定有故事和教訓,否則哲學從哪兒來呢?但從另外的角度來說,一般大家來講哲學就先得有信念。有一個內容特別扯的美劇叫做《美國眾神》,裡面核心的一條思路是“你相信什麼你就是什麼”。其實人類這麼多年來,基本上也是朝這條線路在走的,人類對於未知的東西很難做一個很精確的推導,這時信念就變得非常重要了。

勢高,則圍廣:TiDB 的架構演進哲學

圖 1 最初的基本信念

實際上,我們開始做 TiDB 這個產品的時候,第一個信念就是相信雲是未來。當年 K8s 還沒火,我們就堅定的擁抱了 K8s。第二是不依賴特定硬件、特定的雲廠商,也就是說 TiDB 的設計方向是希望可以 Run 在所有環境上面,包括公有云私有云等等。第三是能支持多種硬件,大家都知道我們支持 X86、AMD64、ARM 等等,可能大家不清楚的是 MIPS,MIPS 典型代表是龍芯,除此之外,TiDB 未來還可以在 GPU 上跑(TiFlash 的後續工作會支持 GPU)。

02早期用戶故事

1、Make it work

有一句話大概是“眼睛裡面寫滿了故事,臉上沒有一點滄桑”,其實現實是殘酷的,歲月一定會給你滄桑的。我們早期的時候,也有相對比較難的時候,這時候就有一些故事關於我們怎麼去經歷、怎麼渡過的。

首先大家做產品之前肯定先做用戶調研,這是通用的流程,我們當初也做過這個事,跟用戶聊。我們通常會說:“我們要做一個分佈式數據庫,自動彈性伸縮,能解決分庫分表的問題,你會用嗎?”用戶說“那肯定啊,現在的分庫分表太痛苦了。”這是最初我們獲取需求最普通的方式,也是我們最容易掉入陷阱的方式,就好像“我有一百萬,你要不要?肯定要。”“我有一瓶水,喝了之後就健康無比,延年益壽你要不要?肯定要。”很容易就得到類似的結論。

所以這個一句話結論的代價是我們進行了長達兩年的開發。在這兩年的時間裡,我們確定了很多的技術方向,比如最初 TiDB 就決定是分層的。很顯然一個複雜的系統如果沒有分層,基本上沒有辦法很好的控制規模和複雜度。TiDB 分兩層,一層是 SQL 層,一層是 key-value 層,那麼到底先從哪一個層開始寫呢?其實從哪層開始都可以,但是總要有一個先後,如何選擇?

這裡就涉及到 TiDB 的第一條哲學。我們做一個產品的時候會不斷面臨選擇,那每次選擇的時候核心指導思想是什麼?核心思想是能一直指導我們持續往前去迭代,所以我們第一條哲學就是:永遠站在離用戶更近的地方去考慮問題。

為什麼我們會定義這樣一條哲學?因為離用戶越近越能更快的得到用戶的反饋,更快的驗證你的想法是不是可行的。顯然 SQL 層離用戶更近,所以我們選擇從 SQL 層寫起。其實一直到現在,絕大多數用戶用 TiDB 的時候根本感受不到 KV 層的存在,用戶寫的都是 SQL,至於底層存儲引擎換成了別的,或者底層的 RocksDB 做了很多優化和改進,這些變化對於用戶關注的接口來說是不可見的。

選擇從 SQL 層開始寫之後,接下來面臨的問題就是怎麼做測試,怎麼去更好的做驗證,怎麼讓整個架構,先能夠完整跑起來。

在軟件開發領域有一條非常經典的哲學:「Make it work, make it right, make it fast」。我想大家每一個學軟件開發的人,或者每一個學計算機的人可能都聽過這樣一句話。所以當時我們就做另外一個決定,先在已有的 KV 上面構建出一個原形,用最短的時間讓整個系統能夠先能 work。

我們在 2015 年的 9 月份開源了第一個版本,當時是沒有存儲層的,需要接在 HBase 上。當這個系統能跑起來之後,我們的第一想法是趕緊找到當初調研時說要用的那些用戶,看看他們是什麼想法,儘快的去驗證我們的想法是不是可行的。因為很多人做產品思維屬於自嗨型,“我做的東西最厲害,只要一推出去肯定一群人蜂擁而至。”抱有這種想法的人太多了,實際上,只有儘快去驗證才是唯一的解決之道,避免產品走入誤區。

勢高,則圍廣:TiDB 的架構演進哲學

圖 2 與調研用戶第二次對話

然而當我跟用戶講,你需要先裝一個 Hadoop,可能還要裝一組 Zookeeper,但用戶說:“我只想要一個更強大的 MySQL,但是讓我裝這一堆東西,你是解決問題還是引入問題?”

這個問題有什麼解決辦法呢?一個辦法是你去解決用戶,可以通過銷售或者通過某些關係跟用戶聊,顯然這是一個不靠譜的思路。作為一個產品型的公司,我們很快就否了這個想法。用戶的本質要求是:你不要給我裝一堆的東西,要真正解決我的問題。所以我們馬上開始啟動分佈式 KV 的開發工作,徹底解決掉這個問題,滿足用戶的要求。

勢高,則圍廣:TiDB 的架構演進哲學

圖 3 開發 TiKV 前的技術考量

開始開發 KV 層時候又會面臨很多技術選擇,我們有很多考量(如圖 3)。

第一點,我們認為作為數據庫最重要的是正確性。假設這個數據庫要用在金融行業,用在銀行、保險、證券,和其他一些非常關鍵的場合的時候,正確性就是無比重要的東西。沒有人會用一個不正確的數據庫。

第二點是實現簡潔、易用。用戶對於一個不簡潔、不易用的東西是無法接受的,所以我們當時的一個想法是一定要做得比 HBase 更加易用,代碼量也要比 HBase 小,所以時至今天 TiDB 代碼量仍然是比 HBase 小得多,大約還不到 HBase 的十分之一。

第三點考慮是擴展性。 TiDB 不僅在整體上是分層的,在存儲層 TiKV 內部也是分層的,所以有非常好的擴展性,也支持 Raw KV API、Transaction API,這個設計後來也收穫了很多用戶的支持,比如一點資訊的同學就是用的 Raw KV API。

第四點就是要求高性能低延遲。

大家對於數據庫的性能和延遲的追求是沒有止境的,但是我們當時並沒有把太多精力花在高性能低延遲上。剛才說到我們有一條哲學是「Make it work, make it right, make it fast」,大家可以看到這句話裡面 「Fast」是放最後的,這一點也是 TiDB 和其他產品有非常大的差異的地方。作為一個技術人員,通常大家看一個產品好不好,就會想:“來,不服跑個分,產品架構、易用性、技術文檔、Community 這些指標都不看,先跑個分讓大家看看行不行”。這個思路真正往市場上去推時是不對的。很多事情的選擇是一個綜合的過程。你可以讓你的汽車跑的巨快無比,上面東西全拆了就留一個發動機和四個輪子,那肯定也是跑得巨快,重量輕,而且還是敞篷車,但沒有一個人會在路上用的。同樣的,選擇 Rust 也是綜合考量的結果。我們看中了 Rust 這個非常具有潛力的語言。當時 Rust 沒有發佈 1.0,還不是一個 stable 版本,但我們相信它會有 1.0。大概過了幾個月,Rust 就發佈了 1.0 版本,證明我們的選擇還是非常正確的。

最後一點就是穩定性。作為一個分佈式數據庫,每一層的穩定性都非常重要。最底下的一個存儲引擎,我們選擇了非常穩定的 RocksDB。不過後來我們也查到幾個 RocksDB 掉數據的 Bug。這也是做數據庫或者說做基礎產品的殘酷性,我們在做產品的過程中找到了 Rust 編譯器的 Bug,XFS 掉數據的 Bug,RocksDB 掉數據的 Bug,好像幾大基礎組件的 Bug 都聚在這裡開會。

接著我們辛辛苦苦幹了三個月,然後就開源了 TiKV,所以這時候看起來沒有那麼多的組件了。我們也不忘初心,又去找了我們當初那個用戶,說我們做了一些改進,你要不要試一試。

勢高,則圍廣:TiDB 的架構演進哲學

圖 4 與調研用戶第三次對話

但是用戶這時候給了一個讓我們非常傷心非常難受的回答:沒有,我們不敢上線,雖然你們的產品聽起來挺好的,但是數據庫後面有很大的責任,心理上的擔心確實是過不去。於是我們回去開始加班加點寫 TiDB Binlog,讓用戶可以把 binlog 同步給 MySQL。

畢竟用戶需要一個 Backup:萬一 TiDB 掛了怎麼辦,我需要切回 MySQL,這樣才放心,因為數據是核心資產。

勢高,則圍廣:TiDB 的架構演進哲學

圖 5 第一個上線用戶的架構圖

所以最終我們第一個用戶上線的時候,整個 TiDB 的架構是這樣的(如圖 5)。用戶通過 Client 連上 TiDB,然後 TiDB 後面就通過 Binlog 同步到 MySQL。後來過了一段時間,用戶就把後面的 MySQL 撤了。我們當時挺好奇為什麼撤了,用戶說,第一個原因是後面 MySQL 撐不起一個集群給它回吐 Binlog,第二就是用了一段時間覺得 TiDB 挺穩定的,然後就不需要 Binlog 備份了。

其實第一個用戶上線的時候,數據量並不算大,大概 800G 的數據,使用場景是 OLTP 為主,有少量的複雜分析和運算,但這少量的複雜分析運算是當時他們選擇 TiDB 最重要的原因。因為當時他們需要每隔幾分鐘算一個圖出來,如果是在 MySQL 上面跑,大約需要十幾分鍾,但他們需要每隔幾分鐘打一個點,後來突然發現第二天才能把前一天的點都打出來,這對於一個實時的系統來說就很不現實了。雖然這個應用實踐只有少部分運算,但也是偏 OLAP,我記得 TiDB 也不算特別快,大概是十幾秒鐘,因為支持了一個並行的 Hash Join。

不管怎樣,這個時候終於有第一個用戶能證明我們做到了「Make it work」。

2、Make it right

接下來就是「Make it right」。大家可能想象不到做一個保證正確性的數據庫這件事情有多麼難,這是一個巨大的挑戰,也有巨大的工作量,是從理論到實踐的距離。

勢高,則圍廣:TiDB 的架構演進哲學

圖 6 理論到實踐的距離

(1)TLA+ 證明

大家可能會想寫程序跟理論有什麼關係?其實在分佈式數據庫領域是有一套方法論的。這個方法論要求先實現正確性,而實現正確的前提是有一個形式化的證明。為了保證整個系統的理論正確,我們把所有的核心算法都用 TLA+ 寫了一遍證明,並且把這個證明開源出去了,如果大家感興趣可以翻看一下(https://github.com/pingcap/tla-plus)。以前寫程序的時候,大家很少想到先證明一下算法是對的,然後再把算法變成一個程序,其實今天還有很多數據庫廠商沒有做這件事。

(2)千萬級別測試用例

在理論上保證正確性之後,下一步是在現實中測試驗證。這時只有一個辦法就是用非常龐大的測試用例做測試。大家通常自己做測試的時候,測試用例應該很少能達到十萬級的規模,而我們現在測試用例的規模是以千萬為單位的。當然如果以千萬為單位的測試用例靠純手寫不太現實,好在我們兼容了 MySQL 協議,可以直接從 MySQL 的測試用例裡收集一些。這樣就能很快驗證整個系統是否具備正確性。

這些測試用例包括應用、框架、管理工具等等。比如有很多應用程序是依賴 MySQL,那直接拿這個應用程序在 TiDB 上跑一下,就知道 TiDB 跟 MySQL 的兼容沒問題,如 Wordpress、無數的 ORM 等等。還有一些 MySQL 的管理工具可以拿來測試,比如 Navicat、PHP admin 等。另外我們把公司內部在用的 Confluence、Jira 後面接的 MySQL 都換成了 TiDB,雖然說規模不大,但是我們是希望在應用這塊有足夠的測試,同時自己「Eat dog food」。

(3)7*24 的錯誤注入測試用例

這些工作看起來已經挺多的了,但實際上還有一塊工作比較消耗精力,叫 7*24 的錯誤注入測試。最早我們也不知道這個測試這麼花錢,我們現在測試的集群已經是幾百臺服務器了。如果創業的時候就知道需要這麼多服務器測試,我們可能就不創業了,好像天使輪的融資都不夠買服務器的。不過好在這個事是一步一步買起來,剛開始我們也沒有買這麼多測試服務器,後來隨著規模的擴大,不斷的在增加這塊的投入。

大家可能到這兒的時候還是沒有一個直觀的感受,說這麼多測試用例,到底是一個什麼樣的感受。我們可以對比看一下行業巨頭 Oracle 是怎麼幹的。

勢高,則圍廣:TiDB 的架構演進哲學

圖 7 前 Oracle 員工的描述(https://news.ycombinator.com/item?id=18442941&utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website)

這是一篇在 HackNews上面的討論,討論的問題是:你覺得這個最壞的、規模最大的代碼是什麼樣子的?下面就有一個 Oracle 的前員工就介紹了 Oracle Database 12.2 這個版本的情況。他說這個整體的源代碼接近 2500 萬行 C 代碼,可能大家維護 25 萬行 C 代碼的時候就會痛不欲生了,可以想想維護這麼多代碼的是一種什麼樣的感受。到現在為止,TiDB 的代碼應該還不到 25 萬行。當然 TiDB 的功能遠遠沒有 Oracle 那麼多,Oracle 的功能其實是很多的,歷史積累一直往上加,加的很兇。

這位 Oracle 前員工介紹了自己在 Oracle 的開發工作的流程,如下圖:

勢高,則圍廣:TiDB 的架構演進哲學

圖 8 Oracle 開發者 fix bug 的過程

比如用戶報了一個 Bug,然後他開始 fix。第一件事是花兩週左右的時間去理解 20 個不同的 flag,看看有沒有可能因為內部亂七八糟的原因來造成這個 Bug。大家可能不知道 MySQL 有多少變量,我剛做 TiDB 的時候也不知道,當時我覺得自己是懂數據庫的,後來去看了一下 MySQL 的 flag 的變量數就驚呆了,但看到 Oracle 的 flag 變量數,那不是驚呆了,是絕望了。大家可能知道開啟 1 個 flag 的時候會對什麼東西有影響,但是要去理解 20 個 flag 開啟時和另外幾個 flag 組合的時候都有什麼影響,可能會崩潰。所以其實精通 Oracle 這件事情,實際上可能比精通 C++ 這件事情更困難的。一個 Oracle 開發者在內部處理這件事情都這麼複雜,更何況是外面的用戶。但 Oracle 確實是功能很強大。

說回這位前 Oracle 員工的描述,他接著添加了更多的 flag 處理一個新的用戶場景的問題,然後加強代碼,最後改完以後會提交一個測試。先在 100 到 200 臺機器上面把這個 Oracle 給 build 出來,然後再對這個 Oracle 去做新的測試。他應該對 Oracle 的測試用例的實際數量了解不深刻,我猜他可能不知道 Oracle 有多少個測試,所以寫的是 “millions of tests”,這顯然太低估了 Oracle 的測試數量。通常情況下,只會看到掛了的測試,看不到全部的測試數量。

下面的步驟更有意思了:Go home,因為整個測試需要 20-30 個小時,跑完之後測試系統反饋了一個報告:掛了 200 多個 test,更茫然的是這 200 tests 他以前都沒見過,這也是 Oracle 非常強大的一個地方,如果一個開發者的代碼提交過去掛掉一兩百個測試,是很正常的事情,因為 Oracle 的測試能 Cover 東西非常多,是這麼多年來非常強大的積累,不停的堆功能的同時就不停的堆測試,當然也不停的堆 flag。所以從另一個角度來看,限制一個系統的功能數量,對於維護來說是非常重要的。

總之,看完這個回覆之後,我對行業前輩們充滿了敬畏之情。

3、Make it fast

(1)新問題

隨著 TiDB 有用戶開始上線,用戶的數量和規模越來越大,這時候就出現了一個很有意思的事情,一部分用戶把 TiDB 當成了可以支持事務、擁有良好實時性的數據倉庫在用,和我們說:我們把公司 Hadoop 換了,數據量十幾 T。

我們就一下開始陷入了深深的思考,因為 TiDB 本來設計的目的不是這個方向,我們想做一個分佈式 OLTP 數據庫,並沒有想說我們要做一個 Data Warehouse。但是用戶的理由讓我們覺得也很有道理,無法反駁——TiDB 兼容 MySQL,會 MySQL 的人很多,更好招人,最重要的是 Hadoop 跑得還不夠快。

雖然我們自己也很吃驚,但這體現了 TiDB 另一方面的價值,所以我們繼續問用戶還有什麼痛點。用戶表示還有一部分查詢不夠快,數據沒辦法做到 shuffle,而且以前用 Spark,TiDB 好像沒有 Spark 的支持。

我們想了想,TiDB 直接連 Spark 也是可以的,但這樣 Spark 對底下沒有感知,事務跑得巨慢,就跟 Spark 接 MySQL 沒什麼差別。我們研究了一下,做出了一個新的東西——TiSpark。TiSpark 就開始能夠同時在 TiDB 上去跑 OLAP 和 OLTP。

勢高,則圍廣:TiDB 的架構演進哲學

圖 9 出現的新問題

就在我們準備改進 TiDB 的數據分析能力的時候,突然又有一大批 TP 用戶上線了,給我們報了一堆問題,比如執行計劃不準確,選不到最優執行計劃,數據熱點分佈不均勻,Raft store 單線程寫入瓶頸,報表跑的慢等等……於是我們制定了 1.0 到 2.X 的計劃,先把用戶提的這些問題一一解決。

這裡有另外一條哲學:將用戶遇到的問題放在第一優先級。我們從產品最初設計和之後 Roadmap 計劃永遠是按照這個原則去做的。

首先,執行計劃不準確的問題。最簡單有效的解決辦法是加一個 Index Hint,就像是“你告訴我怎麼執行,我就怎麼執行,我自己不會自作聰明的選擇”。但這不是長久之計,因為用戶可能是在一個界面上選擇各種條件、參數等等,最後拼成一個 SQL,他們自己沒辦法在裡面加 Index Hint。我們不能決定用戶的使用習慣,所以從這時開始,我們決定從 RBO(Rule Based Optimizer)演進到 CBO(Cost Based Optimizer),這條路也走了非常久,而且還在持續進行。

第二個是熱點數據處理問題。

我們推出了一個熱點調度器,這個可能大家在分佈式數據庫領域第一次聽說,數據庫領域應該是 PingCAP 首創。 熱點調度器會統計、監控整個系統熱點情況,再把這些熱點做一個快速遷移和平衡,比如整個系統有 10 個熱點,某一個機器上有 6 個熱點,這臺機器就會很卡,這時熱點調度器會開始將熱點打散,快速分散到集群的其他機器上去,從而讓整個集群的機器都處於比較正常的負載狀態。

第三個就是解決 Raft store 單線程瓶頸的問題。為了改變 Raft store 單線程,我們大概花了一年多的時間,目前已經在 TiDB 3.0 裡實現了。我們將 Raft store 線程更多耗時的計算變成異步操作,offload 到其它線程。不知道有沒有人會好奇為什麼這個改進會花這麼長時間?我們一直認為數據庫的穩定性第一位的。分佈式系統裡面一致性協議本身也複雜,雖然說 Raft 是比 Paxos 要簡單,但它實際做起來也很複雜,要在一個複雜系統裡支持多線程,並且還要做優化,儘可能讓這個 I/O 能 group 到一起,其實非常耗精力。

第四個就是解決報表跑得慢的問題,這個骨頭特別硬,我們也是啃到今天還在繼續。首先要大幅提升 TiDB 在分析場景下的能力。大家都可以看到我們在發佈每一個版本的時候,都會給出與上一個版本的 TPC-H 性能對比(TPC-H 是一個有非常多的複雜查詢、大量運算的場景)。其次就是高度並行化,充分利用多核,並提供參數控制,這個特性可能很多用戶不知道,我們可以配一下參數,就讓 TiDB 有多個併發在底層做 Scan(https://github.com/pingcap/docs-cn/blob/master/v2.1/sql/tidb-specific.md)。

解決完這些問題,我們終於覺得可以喘口氣了,但喘氣的時間就不到一個星期,很快又有很多用戶的反饋開始把我們淹沒了。因為隨著用戶規模的擴大,用戶反饋問題的速度也變得越來越快,我們處理的速度不一定跟的上用戶的增速。

(2)新呼聲

這時候我們也聽到了用戶的一些「新呼聲」。

有用戶說他們在跑複雜查詢時 OLTP 的查詢延遲變高了,跑一個報表的時候發現 OLTP 開始卡了。這個問題的原因是在跑複雜查詢的時候,SQL 資源被搶佔。我們又想有沒有可能將 OLAP 和 OLTP 的 Workload 分開?於是我們搞了第一個實驗版本,在 TiKV 裡把請求分優先級,放到不同隊列裡面去,複雜 Query 放在第一優先級的隊列, OLTP 放在高優先級。然後我們發現自己是對報表理解不夠深刻,這個方案只能解決一部分用戶的問題,因為有的報表跑起來需要幾個小時,導致隊列永遠是滿的,永遠搶佔著系統的資源。還有一部分用戶的報表沒有那麼複雜,只是希望報表跑得更快、更加實時,比如一個做餐飲 SaaS 的用戶,每天晚上需要看一下餐館營收情況,統計一家餐館時速度還行,如果統計所有餐館的情況,那就另說了。

另外,報表有一些必需品,比如 View 和 Window Function,沒有這些的話 SQL 寫起來很痛苦,缺乏靈活度。

與此同時,用戶關於兼容性和新特性的要求也開始變多,比如希望支持 MySQL 類似的 table partition,還有銀行用戶習慣用悲觀鎖,而 TiDB 是樂觀鎖,遷移過來會造成額外的改造成本(TiDB 3.0 已經支持了悲觀鎖)。

還有用戶有 400T 的數據,沒有一個快速導入的工具非常耗時(當然現在我們有快速導入工具TiDB Lightning),這個問題有一部分原因在於用戶的硬件條件限制,比如說千兆網導入數據。

還有些用戶的數據規模越來越大,到 100T 以上就開始發現十分鐘已經跑不完 GC 了(TiDB 的 GC 是每十分鐘一次),一個月下來 GC 已經整體落後了非常多。

勢高,則圍廣:TiDB 的架構演進哲學

圖 10 用戶的新呼聲

我們當時非常頭痛,收到了一堆意見和需求,壓力特別大,然後趕緊彙總了一下,如圖 10 所示。面對這麼多的需求,我們考慮了兩個點:

  • 哪些是共性需求?
  • 什麼是徹底解決之道?

把共性的需求都列在一塊,提供一個在產品層面和技術層面真正的徹底的解決辦法。

比如圖 10 列舉的那麼多問題,其實真正要解決三個方面:性能、隔離和功能。性能和隔離兼得好像很困難,但是這個架構有非常獨特的優勢,也是可以做得到的。那可以進一步「三者兼得」,同時解決功能的問題嗎?我們思考了一下,也是有辦法的。TiDB 使用的 Raft 協議裡有一個 Raft Learner 的角色,可以不斷的從 Leader 那邊複製數據,我們把數據同步存成了一個列存,剛才這三方面的問題都可以用一個方案去徹底解決了。

首先複雜查詢的速度變快了,眾所周知分析型的數據引擎基本上全部使用的是列存。第二就是強一致性,整個 Raft 協議可以保證從 Learner 讀數據的時候可以選擇一致性的讀,可以從 Leader 那邊拿到 Learner 當前的進度,判斷是否可以對外提供請求。第三個是實時性可以保證,因為是通過 streaming 的方式複製的。

所以這些看上去非常複雜的問題用一個方案就可以解決,並且強化了原來的系統。這個「強化」怎麼講?從用戶的角度看,他們不會考慮 Query 是 OLAP 還是 OLTP,只是想跑這條 Query,這很合理。用一套東西解決用戶的所有問題,對用戶來說就是「強化」的系統。

03關於成本問題的思考

勢高,則圍廣:TiDB 的架構演進哲學

圖 11 成本問題

很多用戶都跟我們反饋了成本問題,用戶覺得全部部署到 SSD 成本有點高。一開始聽到這個反饋,我們還不能理解,SSD 已經很便宜了呀,而且在整個系統來看,存儲機器只是成本的一小部分。後來我們深刻思考了一下,其實用戶說得對,很多系統都是有早晚高峰的,如果在幾百 T 數據裡跑報表,只在每天晚上收工時統計今天營業的狀況,那為什麼要求用戶付出最高峰值的配置呢?這個要求是不合理的,合不合理是一回事,至於做不做得到、怎麼做到是另外一回事。

於是我們開始面臨全新的思考,這個問題本質上是用戶的數據只有一部分是熱的,但是付出的代價是要讓機器 Handle 所有的數據,所以可以把問題轉化成:我們能不能在系統裡面做到冷熱數據分離?能不能支持系統動態彈性的伸縮,伸展熱點數據,用完就釋放?

如果對一個系統來說,峰值時段和非峰值時段的差別在於峰值時段多了 5% 的熱點。我們有必要去 Handle 所有的數據嗎?所以徹底的解決辦法是對系統進行合理的監控,檢測出熱點後,馬上創建一個新的節點,這個新的節點只負責處理熱點數據,而不是把所有的數據做動態的 rebalance,重新搬遷。在峰值時間過去之後就可以把複製出來的熱點數據撤掉,佔的這個機器可以直接停掉了,不需要長時間配備非常高配置的資源,而是動態彈性伸縮的。

TiDB 作為一個高度動態的系統,本身的架構就具有非常強的張力,像海綿一樣,能夠滿足這個要求,而且能根據系統負載動態的做這件事。這跟傳統數據庫的架構有很大的區別。比如有一個 4T 的 MySQL 數據庫,一主一從,如果主庫很熱,只能馬上搞一個等配的機器重掛上去,然後複製全部數據,但實際上用戶需要的只是 5% 的熱數據。而在 TiDB 裡,數據被切成 64MB 一個塊,可以很精確的檢測熱數據,很方便的為熱數據做伸展。這個特性預計在 TiDB 4.0 提供。

這也是一個良好的架構本身帶來的強大的價值,再加上基於 K8s 和雲的彈性架構,就可以得到非常多的不一樣的東西。同樣的思路,如果我要做數據分析,一定是掃全部數據嗎?對於一個多租戶的系統,我想統計某個餐館今天的收入,數據庫裡有成千上萬個餐館,我需要運算的數據只是其中一小塊。如果我要快速做列存計算時,需要把數據全部複製一份嗎?也不需要,只複製我需要的這部分數據就行。這些事情只有一個具有彈性、高度張力的系統才能做到。這是 TiDB 相對於傳統架構有非常不一樣的地方。時至今天,我們才算是把整個系統的架構基本上穩定了,基於這個穩定的架構,我們還可以做更多非常具有張力的事情。

所以,用一句話總結我們解決成本問題的思路是:一定要解決真正的核心的問題,解決最本質的問題。

04關於橫向和縱向發展的哲學

TiDB 還有一條哲學是關於橫向和縱向發展的選擇。

通常業內會給創業公司的最佳建議是優先打“透”一個行業,因為行業內複製成本是最低的,可複製性也是最好的。但 TiDB 從第一天開始就選擇了相反的一條路——「先往通用性發展」,這是一條非常艱難的路,意味著放棄了短時間的複製性,但其實我們換取的是更長時間的複製性,也就是通用性。

因為產品的整體價值取決於總的市場空間,產品的廣泛程度會決定產品最終的價值。早期堅定不移的往通用性上面走,有利於儘早感知整個系統是否有結構性缺陷,驗證自己對用戶需求的理解是否具有足夠的廣度。如果只往一個行業去走,就無法知道這個產品在其他行業的適應性和通用性。如果我們變成了某個行業專用數據庫,那麼再往其他行業去發展時,面臨的第一個問題是自己的恐懼。這恐懼怎麼講呢?Database 應該是一個通用型的東西,如果在一個行業裡固定了,那麼你要如何確定它在其他場景和行業是否具有適應性?

這個選擇也意味著我們會面臨非常大的挑戰,一上來先做最厲害的、最有挑戰的用戶。如果大家去關注整個 TiDB 發展的用戶案例的情況,你會注意到 TiDB 有這樣一個特點,TiDB 是先做百億美金以上的互聯網公司,這是一個非常難的選擇。但大家應該知道,百億美金以上的互聯網公司,在選擇一個數據庫等技術產品的時候,是沒有任何商業上的考量的,對這些公司來說,你的實力是第一位的,一定要能解決他們問題,才會認可你整個系統。但這個也不好做,因為這些公司的應用場景通常都壓力巨大。數據量巨大,QPS 特別高,對穩定性的要求也非常高。我們先做了百億美金的公司之後,去年我們有 80% 百億美金以上的公司用 TiDB,除了把我們當成競爭對手的公司沒有用,其他全部在用。然後再做 30 億美金以上的公司,今年是 10 億美金以上的用戶,實際上現在是什麼樣規模的用戶都有,甭管多少億美金的,“反正這東西挺好用的,我就用了。”所以我們現在也有人專門負責在用戶群裡面回答大家的提問。

其實當初這麼定那個目標主要是考慮數據量,因為 TiDB 作為一個分佈式系統一定是要處理具有足夠數據量的用戶場景,

百億美金以上的公司肯定有足夠的數據,30 億美金的公司也會有,因為他們的數據在高速增長,當我們完成了這些,然後再開始切入到傳統行業,因為在這之前我們經過了穩定性的驗證,經過了規模的驗證,經過了場景的驗證。

勢高,則圍廣:TiDB 的架構演進哲學

圖 12 橫向發展與縱向發展

堅持全球化的技術視野也是一個以橫向優先的發展哲學。最厲害的產品一定是全球在用的。這個事情的最大差異在於視野和格局,而格局最終會反映到人才上,最終競爭不是在 PingCAP 這兩百個員工,也不是現在 400 多個 Contributors,未來可能會有上千人參與整個系統的進化迭代,在不同的場景下對系統進行打磨,所以競爭本質上是人才和場景的競爭。基於這一條哲學,所以才有了現在 TiDB 在新一代分佈式數據庫領域的全面領先,無論是從 GitHub Star 數、 Contributor 數量來看,還是從用戶數據的規模、用戶分佈的行業來看,都是領先的。同樣是在做一個數據庫,大家的指導哲學不一樣會導致產品最終的表現和收穫不一樣,迭代過程也會完全不一樣。我們在做的方向是「攜全球的人才和全球的場景去競爭」。

關於橫向和縱向發展,並不是我們只取了橫向。

2019 年 TiDB 演進的指導思想是:穩定性排第一,易用性排第二,性能第三,新功能第四。這是我在 2018 年經過思考後,把我們發展的優先級做了排序。上半年我們重點關注的是前兩個,穩定性和易用性。下半年會關注縱向發展,「Make it fast」其實是縱向上精耕細作、釋放潛力的事情。這個指導思想看起來好像又跟其他廠商想法不太一樣。

我們前面講的三條哲學裡面,最後一條就是「Make it fast」,如果要修建五百層的摩天大樓,要做的不是搭完一層、裝修一層,馬上給第一層做營業,再去搭第二層。而一定要先把五百層的架構搭好,然後想裝修哪一層都可以。TiDB 就是「摩天大樓先搭架構後裝修」的思路,所以在 TiDB 3.0 發佈之後,我們開始有足夠的時間去做「裝修」的事情。

05總結與展望

說了這麼多故事,如果要我總結一下 2015 - 2019 年外面的朋友對 TiDB 的感受,是下圖這樣的:

勢高,則圍廣:TiDB 的架構演進哲學

圖 13 2015-2019 小結

2015 年,當我們開始做 TiDB 的時候,大家說:啊?這事兒你們也敢幹?因為寫一個數據庫本身非常難,寫一個分佈式數據庫就是無比的難,然後還是國人自主研發。到 2016 年的時候,大家覺得你好像折騰了點東西,聽到點聲音,但也沒啥。到 2017、2018 年,大家看到有越來越多用戶在用。2019 年,能看到更多使用後點讚的朋友了。

我昨天翻了一下 2015 年 4 月 19 日發的一條微博。

勢高,則圍廣:TiDB 的架構演進哲學

圖 14 剛創業時發的微博

當時我們正準備創業,意氣風發發了一條這樣微博。這一堆話其實不重要,大家看一下閱讀量 47.3 萬,有 101 條轉發,44 條評論,然而我一封簡歷都沒收到。當時大家看到我們都覺得,這事兒外國人都沒搞,你行嗎?折騰到今天,我想應該沒有人再對這個問題有任何的懷疑。很多國人其實能力很強了,自信也可以同步跟上來,畢竟我們擁有全球最快的數據增速,很多廠家擁有最大的數據量,對產品有最佳的打磨場景。

想想當時我也挺絕望的,想著應該還有不少人血氣方剛,還有很多技術人員是有非常強大的理想的,但是前面我也說了,總有一個從理想到現實的距離,這個距離很長,好在現在我們能收到很多簡歷。所以很多時候大家也很難想象我們剛開始做這件事情的時候有多麼的困難,以及中間的每一個堅持。只要稍微有一丁點的鬆懈,就可能走了另外一條更容易走的路,但是那條更容易走的路,從長遠上看是一條更加困難的路,甚至是一條沒有出路的路。

勢高,則圍廣:TiDB 的架構演進哲學

圖 15 對 2020 年的展望

最後再說一下 2020 年。在擁有行業複製能力的之後,在產品層面我們要開始向著更高的性能、更低的延遲、更多 Cloud 支持(不管是公有云還是私有云都可以很好的使用 TiDB)等方向縱向發展。同時也會支持我剛剛說的,熱點根據 Workload 自動伸縮,用極小的成本去扛,僅僅需要處理部分熱點的數據,而不是複製整個數據的傳統主-從思路。

大家去想一想,如果整個系統會根據 Workload 自動伸縮,本質上是一個 self-driving 的事情。現在有越來越多的用戶把 TiDB 當成一個數據中臺來用,有了 TiDB 行列混存,並且 TiDB 對用戶有足夠透明度,就相當於是握有了 database 加上 ETL,加上 data warehouse,並且是保證了一致性、實時性的。

昨天我寫完 slides 之後想起了以前看的一個電視劇《大秦帝國》。第一部第九集裡有一段關於圍棋的對話。商鞅執黑子先行,先下在了一個應該是叫天元位置,大約在棋盤的中間。大家知道一般下圍棋的時候都是先從角落開始落子居多。商鞅的對手就說,我許你重下,意思就是你不要開玩笑,誰下這兒啊?於是商鞅說這樣一句話,“中樞之地,輻射四極,雄視八荒”,這也是一個視野和格局的事情。然後對手說:“先生招招高位,步步懸空,全無根基實地”,就是看起來好像是都還挺厲害的,一點實際的基礎都沒有,商鞅說:“旦有高位,豈無實地?”,後來商鞅贏了這盤棋,他解釋道:“

棋道以圍地為歸宿,但必以取勢為根本。勢高,則圍廣”。

這跟我們做 TiDB 其實很像,我們一上來就是先做最難最有挑戰的具有最高 QPS 和 TPS、最大數據量的場景,這就是一個「取勢」的思路,因為「勢高,則圍廣」。所以我們更多時候是像我前面說的那樣,站在哲學層面思考整個公司的運轉和 TiDB 這個產品的演進的思路。這些思路很多時候是大家看不見的,因為不是一個純粹的技術層面或者算法層面的事情。

以上內容來自PingCAP CEO劉奇的分享。

活動推薦

2019年6月21-23日,GIAC全球互聯網架構大會將在深圳舉辦,組委會從互聯網架構最熱門的Cloud-Native、IoT、人工智能等前沿技術、數據及商業智能、大中臺、經典架構、工程文化及管理等領域甄選前沿的有典型代表的技術創新及研發實踐的架構案例,邀請了BAT、美團、滴滴等企業技術專家為我們分享最新的技術成果,識別圖中二維碼即可有機會獲得大會體驗票一張!

勢高,則圍廣:TiDB 的架構演進哲學


分享到:


相關文章: