寫給社區的回顧和展望:TiDB 2019, Level Up !

做者:黃東旭git

2018 年對於 TiDB 和 PingCAP 來講是一個由少年向成年的轉換的一年,若是用一個關鍵字來歸納就是「蛻變」。在這一年很欣喜的看到 TiDB 和 TiKV 在愈來愈多的用戶使用在了愈來愈普遍的場景中,做爲一個剛剛 3 歲多的開源項目,沒有背後強大的社區的話,是沒有辦法取得這樣的進展的。 同時在技術上,2018 年我以爲也交出了一份使人滿意的答卷,TiDB 的幾個主要項目今年一共合併了 4380 個提交,這幾天在整理 2018 年的 Change Log 時候,對比了一下年初的版本,這 4380 個 Commits 背後表明了什麼,這裏簡單寫一個文章總結一下。github

回想起來,TiDB 是最先定位爲 HTAP 的通用分佈式數據庫之一,若是熟悉咱們的老朋友必定知道,咱們最先時候一直都是定位 NewSQL,固然如今也是。可是 NewSQL 這個詞有個問題,到底 New 在哪,解決了哪些問題,很難一目瞭然,其實一開始咱們就想解決一個 MySQL 分庫分表的問題,可是後來慢慢隨着咱們的用戶愈來愈多,使用的場景也愈來愈清晰,不少用戶的場景已經開始超出了一個「更大的 MySQL 」的使用範圍,因而咱們從實驗室和學術界找到了咱們以爲更加清晰的定義:HTAP,但願能構建一個融合 OLTP 和 OLAP 通用型分佈式數據庫。可是要達成這個目標很是複雜,咱們的判斷是若是不是從最底層從新設計,很難達到咱們的目標,咱們認爲這是一條更困難可是正確的路,如今看來,這條路是走對了,並且將來會越走越快,越走越穩。算法

在 SQL 層這邊,TiDB 選擇了 MySQL 的協議兼容,一方面持續的增強語法兼容性,另外一方面選擇自研優化器和執行器,帶來的好處就是沒有任何歷史負擔持續優化。回顧今年最大的一個工做應該是重構了執行器框架,TiDB的 SQL 層仍是經典的 Volcano 模型,咱們引入了新的內存數據結構 Chunk 來批量處理多行數據,並對各個算子都實現了基於 Chunk 的迭代器接口,這個改進對於 OLAP 請求的改進很是明顯,在 TiDB 的 TPC-H 測試集上能看出來(https://github.com/pingcap/docs-cn/blob/master/benchmark/tpch.md),Chunk 的引入爲咱們全面的向量化執行和 CodeGen 支持打下了基礎。目前在 TiKV 內部對於下推算子的執行尚未使用 Chunk 改造,不過這個已經在計劃中,在 TiKV 中這個改進,預期對查詢性能的提高也將很是顯著。數據庫

另外一方面,一個數據庫查詢引擎最核心的組件之一:優化器,在今年也有長足的進步。咱們在 2017 年就已經全面引入了基於代價的 SQL 優化(CBO,Cost-Based Optimization),咱們在今年改進了咱們的代價評估模型,加入了一些新的優化規則,同時實現了 Join Re-Order 等一系列優化,從結果上來看,目前在 TPC-H 的測試集上,對於全部 Query,TiDB 的 SQL 優化器大多已給出了最優的執行計劃。CBO 的另外一個關鍵模塊是統計信息收集,在今年,咱們引入了自動的統計信息收集算法,使優化器的適應性更強。另外針對 OLTP 的場景 TiDB 仍然保留了輕量的 RBO 甚至直接 Bypass 優化器,以提高 OLTP 性能。另外,感謝三星韓國研究院的幾位工程師的貢獻,他們給 TiDB 引入了 Query Plan Cache,對高併發場景下查詢性能的提高也很明顯。另外在功能上,咱們引入了 Partition Table 的支持,對於一些 Partition 特性很明顯的業務,TiDB 可以更加高效的調度數據的寫入讀取和更新。安全

一直以來,TiDB 的 SQL 層做爲純 Go 語言實現的最完備的 MySQL 語法兼容層,不少第三方的 MySQL 工具在使用着 TiDB 的 SQL Parser,其中的優秀表明好比小米的 Soarhttps://github.com/XiaoMi/soar)。 爲了方便第三方更好的複用 TiDB Parser,咱們在 2018 年將 Parser 從主項目中剝離了出來,成爲了一個獨立的項目:pingcap/parser,但願能幫到更多的人。網絡

說到 TiDB 的底層存儲 TiKV 今年也有不少讓人眼前一亮的更新。在 TiKV 的基石——一致性算法 Raft 這邊,你們知道 TiKV 採用的是 Multi-Raft 的架構,內部經過無數個 Raft Group 動態的分裂、合併、移動以達到動態伸縮和動態負載均衡。咱們在今年仍然持續在擴展 Multi-Raft 的邊界,咱們今年加入了動態的 Raft Group 合併,以減輕元信息存儲和心跳通訊的負擔;給 Raft 擴展了 Learner 角色(只同步 Log 不投票的角色) 爲 OLAP Read 打下基礎;給 Raft 的基礎算法加入了 Pre-Vote 的階段,讓整個系統在異常網絡狀態下可靠性更高。數據結構

<center>Raft Group Merge</center>架構

在性能方面,咱們花了很大的精力重構了咱們單機上多 Raft Group 的線程模型(https://github.com/tikv/tikv/pull/3568), 雖然尚未合併到 master 分支,在咱們測試中,這個優化帶來了兩倍以上的吞吐提高,同時寫入延遲下降至如今的版本的 1/2 ,預計在這兩週咱們會完成這個巨大的 PR 的 Code Review,各位同窗能夠期待一下 :)併發

第三件事情是咱們開始將 TiKV 的本地存儲引擎的接口完全抽象出來,目標是能作到對 RocksDB 的弱耦合,這點的意義很大,無論是社區仍是咱們本身,對新的單機存儲引擎支持將變得更加方便。負載均衡

在 TiKV 社區這邊,今年的另一件大事是加入了 CNCF,變成了 CNCF 的託管項目,也是 CNCF 基金會第一個非結構化數據庫項目。 後來不少朋友問我,爲何捐贈的是 TiKV 而不是 TiDB,其實主要的緣由就像我在當天的一條 Tweet 說的,TiKV 更像是的一個更加通用的組件,當你有一個能夠彈性伸縮的,支持跨行 ACID 事務的 Key-Value 數據庫時,你會發現構建其餘不少可靠的分佈式系統會容易不少,這在咱們以後的 TiDB Hackathon 中獲得了很好的體現。另外社區已經開始出現基於 TiKV 構建的 Redis 協議支持,以及分佈式隊列系統,例如 meitu/titan 項目。做爲一個基金會項目,社區不只僅能夠直接使用,更可以將它做爲構建其餘系統的基石,我以爲更加有意義。相似的,今年咱們將咱們的 Raft 實現從主項目中獨立了出來(pingcap/raft-rs),也是但願更多的人能從中受益。

「……其 KV與 SQL分層的方式,恰好符合咱們提供 NoSQL 存儲和關係型存儲的需求,另外,PingCAP 的文檔齊全,社區活躍,也已經在實際應用場景有大規模的應用,公司在北京,技術交流也很是方便,事實證實,後面提到的這幾個優點都是對的……」 ——美圖公司 Titan 項目負責人任勇全對 TiKV 的評論

在 TiDB 的設計之初,咱們堅決將調度和元信息從存儲層剝離出來(PD),如今看來,好處正漸漸開始顯示出來。今年在 PD 上咱們花了很大精力在處理熱點探測和快速熱點調度,調度和存儲分離的架構讓咱們無論是在開發,測試仍是上線新的調度策略時效率很高。瞬時熱點一直是分佈式存儲的最大敵人,如何快速發現和處理,咱們也有計劃嘗試將機器學習引入 PD 的調度中,這是 2019 會嘗試的一個事情。整體來講,這個是一個長期的課題。

我在幾個月前的一篇文章提到過 TiDB 爲何從 Day-1 起就 All-in Kubernetes (《十問 TiDB:關於架構設計的一些思考》),今年很欣喜的看到,Kubernetes 及其周邊生態已經漸漸成熟,已經開始有不少公司用 Kubernetes 來運行 Mission-critical 的系統,這也佐證了咱們當年的判斷。2018 年下半年,咱們也開源了咱們的 TiDB Operator(https://github.com/pingcap/tidb-operator),這個項目並不止是一個簡單的在 K8s 上自動化運維 TiDB 的工具,在咱們的戰略裏面,是做爲 Cloud TiDB 的重要基座,過去設計一個完善的多租戶系統是一件很是困難的事情,同時調度對象是數據庫這種帶狀態服務,更是難上加難,TiDB-Operator 的開源也是但願可以藉助社區的力量,一塊兒將它作好。

image

<center>多租戶 TiDB</center>

今年還作了一件很大的事情,咱們成立了一個新的部門 TEP(TiDB Enterprise Platform)專一於商業化組件及相關的交付質量控制。做爲一個企業級的分佈式數據庫,TiDB 今年完成了商業化從0到1的跨越,愈來愈多的付費客戶證實 TiDB 的核心的成熟度已經能夠委以重任,成立 TEP 小組也是但願在企業級產品方向上繼續發力。從 TiDB-Lightning(MySQL 到 TiDB 高速離線數據導入工具)到 TiDB-DM(TiDB-DataMigration,端到端的數據遷移-同步工具)能看到發力的重點在讓用戶無縫的從上游遷移到 TiDB 上。另外一方面,TiDB-Binlog 雖然不是今年的新東西,可是今年這一年在無數個社區用戶的場景中鍛鍊,愈來愈穩定。作工具可能在不少人看來並非那麼「高科技」, 不少時候也確實是髒活累活,可是這些通過無數用戶場景打磨的周邊工具和生態纔是一個成熟的基礎軟件的護城河和競爭壁壘,在 PingCAP 內部,負責工具和外圍系統研發的團隊規模幾乎和內核團隊是 1:1 的配比,重要性可見一斑。

在使用場景上,TiDB 的使用規模也愈來愈大,下面這張圖是咱們統計的咱們已知 TiDB 的用戶,包括上線和準上線的用戶,從 1.0 GA 後,幾乎是以一個指數函數的曲線在增加,應用的場景也從簡單的 MySQL Sharding 替代方案變成橫跨 OLTP 到實時數據中臺的通用數據平臺組件。

<center>TiDB 的用戶數統計</center>

今年幾個比較典型的用戶案例,從 美團 的橫跨 OLTP 和實時數倉的深度實踐,到 轉轉 的 All-in TiDB 的體驗,再到 TiDB 支撐的北京銀行的核心交易系統。能夠看到,這些案例從互聯網公司的離線線數據存儲到要求極端 SLA 的傳統銀行核心交易系統,TiDB 在這些場景裏面都發光發熱,甚至有互聯網公司(轉轉)都喊出了 All-in TiDB 的口號,咱們很是珍視這份信任,必定盡全力作出漂亮的產品,高質量的服務好咱們的用戶和客戶。另外一方面,TiDB 也慢慢開始產生國際影響力的,在線視頻巨頭葫蘆軟件(Hulu.com),印度最大的在線票務網站 BookMyShow,東南亞最大的電商之一 Shopee 等等都在大規模的使用 TiDB,在北美和歐洲也已經很多準上線和測試中的的巨頭互聯網公司。

簡單回顧了一下過去的 2018 年,咱們看看將來在哪裏。

其實從咱們在 2018 年作的幾個比較大的技術決策就能看到,2019 年將是上面幾個方向的延續。大的方向的幾個指導思想是:

  1. Predicable. (靠譜,在更普遍的場景中,作到行爲可預測。)

  2. Make it right before making it fast.(穩定,先作穩,再作快。)

  3. Ease of use. (好用,簡單交給用戶,複雜留給本身。)

對於真正的 HTAP 場景來講,最大的挑戰的是如何很好的作不一樣類型的 workload 隔離和數據結構根據訪問特性自適應。咱們在這個問題上給出了本身的答案:經過拓展 Raft 的算法,將不一樣的副本存儲成異構的數據結構以適應不一樣類型的查詢。

這個方法有如下好處:

  1. 自己在 Multi-Raft 的層面上修改,不會出現由數據傳輸組件形成的瓶頸(相似 Kafka 或者 DTS),由於 Multi-Raft 自己就是可擴展的,數據同步的單位從 binlog,變成 Raft log,這個效率會更高,進一步下降了同步的延遲。

  2. 更好的資源隔離,經過 PD 的調度,能夠真正將不一樣的副本調度到隔離的物理機器上,真正作到互不影響。

<center>TiDB 2019 年會變成這個樣子</center>

<center>Learner 在 HTAP 中的應用</center>

在執行器方面,咱們會繼續推動向量化,不出意外的話,今年會完成全部算子的全路徑的向量化執行。

這個 HTAP 方案的另外一個關鍵是存儲引擎自己。2019 年,咱們會引入新的存儲引擎,固然第一階段仍然會繼續在 RocksDB 上改進,改進的目標仍然是減少 LSM-Tree 自己的寫放大問題。選用的模型是 WiscKey (FAST16,https://www.usenix.org/system/files/conference/fast16/fast16-papers-lu.pdf ),WiscKey 的核心思想是將 Value 從 LSM-Tree 中剝離出來,以減小寫放大,若是關注 TiKV 的朋友,已經能注意到咱們已經在前幾天將一個新存儲引擎 Titan(PingCAP 的 Titan,很遺憾和美圖那個項目重名了) 合併到了 TiKV 的主幹分支,這個 Titan 是咱們在 RocksDB 上的 WiscKey 模型的一個實現,除了 WiscKey 的核心自己,咱們還加入了對小 KV 的 inline 等優化,Titan 在咱們的內部測試中效果很好,對長度隨機的 key-value 寫入的吞吐基本能達到原生 RocksDB 的 2 - 3 倍,固然性能提高並非我最關注的,這個引擎對於 TiDB 最大的意義就是,這個引擎將讓 TiDB 適應性更強,作到更加穩定,更加「可預測」。

<center>TiKV 新的本地存儲引擎 Titan</center>

在 Titan 走向穩定的同時,咱們也在調研從頭構建一個更適合 TiDB 的 OLTP workload 的存儲引擎,前面說到 2018 年作了抽象 TiKV 的本地存儲引擎的事情就是爲了這個打基礎,固然咱們仍然會走 LSM-Tree 的路線。這裏多提一句,其實不少人都誤解了 LSM-Tree 模型的真正優點,在我看來並非性能,而是:作到可接受的性能的同時,LSM-Tree 的實現很是簡單可維護,只有簡單的東西才能夠依賴,這個決定和咱們在 Raft 與 Paxos 之間的選擇偏好也是一致的。另外 LSM-Tree 的設計從宏觀上來講,更加符合「冷熱分層」以適配異構存儲介質的想法,這個我相信是將來在存儲硬件上的大趨勢。

至於在 OLAP 的存儲引擎這邊,咱們走的就是純列式存儲的路線了,可是會和傳統的 Columnar 數據結構的設計不太同樣,這塊的進展,咱們會在 1 月 19 號的 TiDB DevCon 上首秀,這裏先賣個關子。

另外一個大的方向是事務模型,目前來講,TiDB 從誕生起,事務模型就沒有改變過,走的是傳統的 Percolator 的 2PC。這個模型的好處是簡單,吞吐也不是瓶頸,可是一個比較大的問題是延遲,尤爲在跨數據中心的場景中,這裏的延遲主要表如今往 TSO 拿時間戳的網絡 roundtrip 上,固然了,我目前仍然認爲時鐘(TSO)是一個必不可少組件,在不下降一致性和隔離級別的大前提下也是目前咱們的最好選擇,另外 Percolator 的模型也不是沒有辦法對延遲進行優化,咱們其實在 2018 年,針對 Percolator 自己作了一些理論上的改進,減小了幾回網絡的 roundtrip,也在年中書寫了新的 2PC 改進的完整的 TLA+ 的證實(https://github.com/pingcap/tla-plus/blob/master/OptimizedCommitTS/OptimizedCommitTS.tla),證實了這個新算法的正確性,2019 年在這塊還會有比較多的改進,其實咱們一直在思考,怎麼樣可以作得更好,選擇合適的時機作合適的優化。另一方面,在事務模型這方面,2PC 在理論和工程上還有不少能夠改進的空間,可是如今的當務之急繼續的優化代碼結構和總體的穩定性,這部分的工做在將來一段時間仍是會專一在理論和證實上。另一點你們能夠期待的是,2019 年咱們會引入安全的 Follower/Learner Read,這對保持一致性的前提下讀的吞吐會提高,另外在跨數據中心的場景,讀的延遲會更小。

差很少就這些吧,最後放一句我特別喜歡的丘吉爾的一句名言做爲結尾。

Success is not final, failure is not fatal: it is the courage to continue that counts.

成功不是終點,失敗也並不是終結,最重要的是繼續前進的勇氣。

相關文章
相關標籤/搜索