在 TiDB DevCon 2019 上,我司聯合創始人兼 CTO 黃東旭分享了對數據庫行業大趨勢以及將來數據庫技術的見解。如下是演講實錄,enjoy~git
你們今天在這裏看到了 TiDB 社區用戶實踐分享和咱們本身的一些技術進展和展望,還有很是好玩的 Demo Show,正好在大會結束以前,我想跟你們聊一聊我心目中將來的 Database 應該是一個什麼樣子。github
其實咱們並非一個特別擅長髮明名詞的公司,我記得咱們第一次去用 HTAP 這個詞的時候,應該是 2016 左右。在使用 HTAP 這個詞的時候,咱們市場部同事還跟咱們說 HTAP 這個詞歷來沒人用過,都是論文裏的詞,你們都不知道,你把大家公司的產品定位改爲這個別人都不知道怎麼辦?咱們後來仔細想,仍是以爲 HTAP 這個方向是一個更加適合咱們的方向,因此仍是選了 HTAP 這個詞。如今很欣喜的看到如今各類友商、後來的一些數據庫,都開始爭相說 HTAP,就是說獲得了同行的承認。算法
那麼在 HTAP 的將來應該是一個什麼樣子,我但願可以在今年這個 Talk 裏面先說一說,可是這個題目起的有點不太謙虛,因此我特意加了一個「Near」, 分享一下這一年、兩年、三年咱們想作什麼,和對行業大趨勢的展望。數據庫
今天咱們的分享的一個主題就是:「咱們只作用戶想要的東西,並非要去作一個完美的東西」。其實不少工程師包括咱們本身,都會有一個小小的心理的潔癖,就是想要作一個超級快、超級牛的東西,可是作出來一個數據庫,單機跑分一百萬 TPS ,其實用戶實際業務就須要 3000,而後全部的用戶還會說我須要這些東西,好比須要 Scalability(彈性擴展), Super Large 的數據量,最好是個人業務一行代碼都不用改,並且 ACID 可以徹底的知足,怎麼踹都踹不壞,機器壞了能夠高可用,業務層徹底不用動, 另外能夠在跑 OLTP 的同時,徹底不用擔憂任何資源隔離地跑 OLAP(這裏不是要說你們的願望不切實際,而是很是切實際,咱們也以爲數據庫自己就應該是這樣的。因此你們記住這幾個要點,而後慢慢看 TiDB 究竟是不是朝着這個方向發展的)。本質上來講用戶的需求就是「大一統」。看過《魔戒》的同窗都知道這句話 :ONE RING TO RULE THEM ALL,就是一套解決方案去解決各類問題。緩存
過去不少,包括一些行業的大佬以前說在各類環境下都要出一個數據庫來解決特定的一個問題,可是其實看上去咱們想走的方案仍是儘量在一個平臺裏面,儘量大範圍去解決用戶的問題。由於不一樣的產品之間去作數據的交互和溝通,實際上是蠻複雜的。網絡
這張圖(圖 2)什麼意思呢?就是不少人設計系統的時候,老是會陷入跑分思惟,就是說這個東西在實驗室或者說在一個特定的 Workload 下,跑得巨快無比。若是你們去看一下大概 2000 年之後關於數據庫的論文,不少在作一個新的模型或者新的系統的時候,都會說 TPCC 可以跑到多大,而後把 Oracle 摁在地上摩擦,這樣的論文有不少不少不少。可是你們回頭看看 Oracle 仍是王者。因此大多數實驗室的產品和工程師本身作的東西都會陷入一個問題,就是想象中的個人賽道應該是一個圖 2 那樣的,但實際上用戶的業務環境是下面這樣的(圖 3)。不少你們在廣告上看到特別牛的東西,一放到生產環境或者說放到本身的業務場景裏面就不對了,而後陷入各類各樣的比較和糾結的煩惱之中。數據結構
TiDB 的定位或者說咱們想作的事情,並非在圖 2 那樣的賽道上,跑步跑得巨快,全世界沒人在短跑上跑得過我,咱們不想作這樣。或者說,咱們其實也能跑得很快,可是並不想把全部優點資源全都投入到一個用戶可能一生都用不到的場景之中。咱們其實更像是作鐵人三項的,由於用戶實際應用場景可能就是一個土路。這就是爲何 TiDB 的設計放在第一位的是「穩定性」。架構
咱們一直在想能不能作一個數據庫,怎麼踹都踹不壞,而後全部的異常的情況,或者它的 Workload 都是可預期的。我以爲不少人遠遠低估了這個事情的困難程度,其實咱們本身也特別低估了困難程度。大概 4 年前出來創業的時候,咱們就是想作這麼一個數據庫出來,我跟劉奇、崔秋三我的也就三個月作出來了。可是到如今已經 4 年過去了,咱們的目標跟當年仍是如出一轍。不忘初心,不是忘不掉,而是由於初心還沒達到,怎麼忘?其實把一個數據庫作穩,是很難很難的。併發
並且咱們這個團隊的平均年齡可能也就在二十到三十歲之間,爲何咱們如此年輕的一個團隊,可以去作數據庫這麼古老的一件事情。其實也是得益於整個 IT 行業這幾年很是大的發展。圖 4 是這幾年發展起來的 SSD,內存愈來愈大,萬兆的網卡,還有各類各樣的多核的 CPU,虛擬化的技術,讓過去不少不可能的事情變成了可能。框架
舉一個例子吧,好比極端一點,你們可能在上世紀八九十年代用過這種 5 寸盤、3 寸盤,我針對這樣的磁盤設計一個數據結構,如今看上去是個笑話是吧?由於你們根本沒有人用這樣的設備了。在數據庫這個行業裏面不少的假設,在如今新的硬件的環境下其實都是不成立的。好比說,爲何 B-Tree 就必定會比 LSM-Tree 要快呢?不必定啊,我跑到 Flash 或者 NVMe SSD 、Optane 甚至將來的持久化內存這種介質上,那數據結構設計徹底就發生變化了。過去可能須要投入不少精力去作的數據結構,如今暴力就行了。
同時在軟件上也發生了不少不少的變革,圖 5 左上角是 Wisckey 那篇論文裏的一個截圖,還有一些分佈式系統上的新的技術,好比 2014 年 Diego 發表了 Raft 這篇論文,另外 Paxos 這幾年在各類新的分佈式系統裏也用得愈來愈多。
因此我以爲這幾年咱們遇上了一個比較好的時代,就是無論是軟件仍是硬件,仍是分佈式系統理論上,都有了一些比較大突破,因此咱們基礎纔可以打得比較好。
除了有這樣的新的硬件和軟件以外,我以爲在業務場景上也在發生一些比較大變化。過去,可能十年前就是我剛開始參加工做的時候,線上的架構基本就是在線和離線兩套系統,在線是 Oracle 和 MySQL,離線是一套 Hadoop 或者一個純離線的數據倉庫。但最近這兩年愈來愈多的業務開始強調敏捷、微服務和中臺化,因而產生了一個新的數據類型,就是 warm data,它須要像熱數據這樣支持 transaction、支持實時寫入,可是須要海量的數據都能存在這個平臺上實時查詢, 並非離線數倉這種業務。
因此對 warm data 來講,過去在 TiDB 以前,實際上是並無太好的辦法去很優雅的作一層大數據中臺架構的,「the missing part of modern data processing stack」,就是在 warm data 這方面,TiDB 正好去補充了這個位置,因此纔能有這麼快的增加。固然這個增加也是得益於 MySQL 社區的流行。
想象一下,咱們若是在過去要作這樣很簡單的業務(圖 7),好比在美國的訂單庫跟在中國的訂單庫可能都是在不一樣的數據庫裏,用戶庫多是另一個庫,而後不一樣的業務多是操做不一樣的庫。若是我想看看美國的消費者裏面有哪些在中國有過消費的,就是這麼一條 SQL。過去若是沒有像 TiDB 這樣的東西,你們想象這個東西該怎麼作?
假如說這兩邊的數據量都特別大,而後已經分庫分表了。過去可能只能次日才能夠看到前一天的數據,由於中間好比說一個 T+1 要作一個 ETL 到一個 data ware house 裏。或者厲害一點的架構師可能會說,我能夠作一套實時的 OLAP 來作這個事情,怎麼作呢?好比說 MySQL 中間經過一個 MQ 再經過 Hadoop 作一下 ETL,而後再導到 Hadoop 上作一個冷的數據存儲,再在上面去跑一個 OLAP 作實時的分析。先不說這個實時性到底有多「實時」,你們仔細算一算,這套架構須要的副本數有多少,好比 M 是個人業務數,N 是每個系統會存儲的 Replica,拍腦殼算一下就是下面這個數字(圖 9 中的 R )。
因此你們其實一開始在過去說,TiDB 這個背後這麼多 Replica 很差,但其實你想一想,你本身在去作這個業務的時候,你們在過去又能怎麼樣呢?因此我以爲 TiDB 在這個場景下去統一一箇中臺,是一個大的趨勢。今天在社區實踐分享上也看到不少用戶都要提到了 TiDB 在中臺上很是好的應用。
回顧完行業和應用場景近年來的一些變化以後,咱們再說說將來。假設要去作一個面向將來的數據庫,會使用哪些技術?
第一個大的趨勢就是日誌,「log is the new database」 這句話應該也是業界的一個共識吧。如今若是有一個分佈式數據庫的複製協議,仍是同步一個邏輯語句過去,或者作 binlog 的複製,那其實還算比較 low 的。
上面圖 11 左半部分是 Hyper,它是慕尼黑工業大學的一個實驗性數據庫項目,它作了一些分析,第一個柱形是正常的 SQL 語句的執行時間,好比說直接把一語句放到另一個庫裏去執行,耗時這麼多。第二個柱形是用邏輯日誌去存放,耗時大概能快 23%,第三個柱形能看到若是是存放物理日誌能快 56%。因此你們仔細想一想,TiDB 的架構裏的 TiFlash 其實同步的是 Raft 日誌,而並非同步 Binlog 或者其餘的。
上面圖 11 右半部分是 Aurora,它的架構就不用說了,同步的都是 redo log 。其實他的好處也很明顯,也比較直白,就是 I/O 更小,網絡傳輸的 size 也更小,因此就更快。
而後在這一塊 TiDB 跟傳統的數據庫有點不同的就是,其實若是不少同窗對 TiDB 的基礎架構不太理解的話就以爲, Raft 不是一個必定要有 Index 或者說是必定強順序的一個算法嗎?那爲何能作到這樣的亂序的提交?其實 TiDB 並非單 Raft 的架構,而是一個多 Raft 的架構,I/O 能夠發生在任何一個 Raft Group 上。傳統的單機型數據庫,就算你用更好的硬件都不可能達到一個線性擴展,由於不管怎麼去作,都是這麼一個架構不可改變。好比說我單機上 Snapshot 加 WAL,無論怎麼寫, 老是在 WAL 後面加,I/O 老是發生在這。但 TiDB 的 I/O 是分散在多個 Raft Group、多個機器上,這是一個很本質的變化,這就是爲何在一些場景下,TiDB 可以獲取更好的吞吐。
第二個大趨勢是全面的向量化。向量化是什麼意思?我舉個簡單的例子。好比我要去算一個聚合,從一個表裏面去求某一列的總量數據,若是我是一個行存的數據庫,我只能把這條記錄的 C 取出來,而後到下一條記錄,再取再取再取,整個 Runtime 的開銷也好,還有去掃描、讀放大的每一行也好,都是頗有問題的。可是若是在內存裏面已是一個列式存儲,是很緊湊的結構的話,那會是很是快的。
這裏面其實也有一些挑戰。咱們花了大概差很少 2018 年一年的時間去作向量化的改造,其實還挺難的。爲何?首先 TiDB SQL 引擎是用了 Volcano 模型,這個模型很簡單,就是遍歷一棵物理計劃的樹,不停的調 Next,每一次 Next 都是調用他的子節點的 Next,而後再返回結果。這個模型有幾個問題:第一是每一次都是拿一行,致使 CPU 的 L一、L2 這樣的緩存利用率不好,就是說沒有辦法利用多 CPU 的 Cache。第二,在真正實現的時候,它內部的架構是一個多級的虛函數調用。你們知道虛函數調用在 Runtime 自己的開銷是很大的,在《MonetDB/X100: Hyper-Pipelining Query Execution》裏面提到,在跑 TPC-H 的時候,Volcano 模型在 MySQL 上跑,大概有 90% 的時間是花在 MySQL 自己的 Runtime 上,而不是真正的數據掃描。因此這就是 Volcano 模型一個比較大的問題。第三,若是使用一個純靜態的列存的數據結構,你們知道列存特別大問題就是它的更新是比較麻煩的, 至少過去在 TiFlash 以前,沒有一個列存數據庫可以支持作增刪改查。那在這種狀況下,怎麼保證數據的新鮮?這些都是問題。
TiDB 已經邁出了第一步,咱們已經把 TiDB SQL 引擎的 Volcano 模型,從一行一行變成了一個 Chunk 一個 Chunk,每一個 Chunk 裏面是一個批量的數據,因此聚合的效率會更高。並且在 TiDB 這邊作向量化以外,咱們還會把這些算子推到 TiKV 來作,而後在 TiKV 也會變成一個全向量化的執行器的框架。
另一個比較大的話題,是 Workload Isolation。今天咱們在演示的各類東西都有一箇中心思想,就是怎麼樣儘量地把 OLTP 跟 OLAP 隔離開。這個問題在業界也有不一樣的聲音,包括咱們的老前輩 Google Spanner,他們實際上是想作一個新的數據結構,來替代 Bigtable-Like SSTable 數據結構,這個數據結構叫 Ressi,你們去看 2018 年 《Spanner: Becoming a SQL System》這篇 Paper 就能看到。它其實表面上看仍是行存,但內部也是一個 Chunk 變成列存這樣的一個結構。但咱們以爲即便是換一個新的數據結構,也沒有辦法很好作隔離,由於畢竟仍是在一臺機器上,在同一個物理資源上。最完全的隔離是物理隔離。
咱們在 TiFlash 用了好幾種技術來去保證數據是更新的。一是增長了 Raft Leaner,二是咱們把 TiDB 的 MVCC 也實如今了 TiFlash 的內部。第三在 TiFlash 這邊接觸了更新(的過程),在 TiFlash 內部還有一個小的 Memstore,來處理更新的熱數據結果,最後查詢的時候,是列存跟內存裏的行存去 merge 並獲得最終的結果。TiFlash 的核心思想就是經過 Raft 的副原本作物理隔離。
這個有什麼好處呢?這是咱們今天給出的答案,可是背後的思考,究竟是什麼緣由呢?爲何咱們不能直接去同步一個 binlog 到另一個 dedicate 的新集羣上(好比 TiFlash 集羣),而必定要走 Raft log?最核心的緣由是,咱們認爲 Raft log 的同步能夠水平擴展的。由於 TiDB 內部是 Mult-Raft 架構,Raft log 是發生在每個 TiKV 節點的同步上。你們想象一下,若是中間是經過 Kafka 溝通兩邊的存儲引擎,那麼實時的同步會受制於中間管道的吞吐。好比圖 14 中綠色部分一直在更新,另外一邊併發寫入每秒兩百萬,可是中間的 Kafka 集羣可能只能承載 100 萬的寫入,那麼就會致使中間的 log 堆積,並且下游的消費也是不可控的。而經過 Raft 同步, Throughput 能夠根據實際存儲節點的集羣大小,可以線性增加。這是一個特別核心的好處。
說完了存儲層,接下來講一說執行器。TiDB 在接下來會作一個很重要的工做,就是全面地 leverage SIMD 的計算。我先簡單科普一下 SIMD 是什麼。
如圖 15,在作一些聚合的時候,有這樣一個函數,我要去作一個求和。正常人寫程序,他就是一個 for 循環,作累加。可是在一個數據庫裏面,若是有一百億條數據作聚合,每一次執行這條操做的時候,CPU 的這個指令是一次一次的執行,數據量特別大或者掃描的行數特別多的時候,就會很明顯的感覺到這個差異。
現代的 CPU 會支持一些批量的指令,好比像 _mm_add_epi32,能夠一次經過一個32 位字長對齊的命令,批量的操做 4 個累加。看上去只是省了幾個 CPU 的指令,但若是是在一個大數據量的狀況下,基本上能獲得 4 倍速度的提高。
順便說一句,有一個很大的趨勢是 I/O 已經不是瓶頸了,你們必定要記住我這句話。再過幾年,若是想去買一塊機械磁盤,除了在那種冷備的業務場景之外,我相信你們可能都要去定製一塊機械磁盤了。將來必定 I/O 不會是瓶頸,那瓶頸會是什麼?CPU。咱們怎麼去用新的硬件,去儘量的把計算效率提高,這個纔是將來我以爲數據庫發展的重點。好比說我怎麼在數據庫裏 leverage GPU 的計算能力,由於若是 GPU 用的好,其實能夠很大程度上減小計算的開銷。因此,若是在單機 I/O 這些都不是問題的話,下一個最大問題就是怎麼作好分佈式,這也是爲何咱們一開始就選擇了一條看上去更加困難的路:我要去作一個 Share-nothing 的數據庫,並非像 Aurora 底下共享一個存儲。
在今天你們其實看不到將來十年數據增加是怎樣的,回想十年前你們能想到如今咱們的數據量有這麼大嗎?不可能的。因此新的架構或者新的數據庫,必定要去面向咱們未知的 Scale 作設計。好比你們想象如今有業務 100T 的數據,目前看可能還挺大的,可是有沒有辦法設計一套方案去解決 1P、2P 這樣數據量的架構?在海量的數據量下,怎麼把數據很靈活的分片是一個很大的學問。
爲何分庫分表在對比 TiDB 的時候,咱們會以爲分庫分表是上一代的方案。這個也很好理解,核心的緣由是分庫分表的 Router 是靜態的。若是出現分片不均衡,好比業務可能按照 User ID 分表,可是發現某一地方/某一部分的 User ID 特別多,致使數據不均衡了,這時 TiDB 的架構有什麼優點呢?就是 TiDB 完全把分片這個事情,從數據庫裏隔離了出來,放到了另一個模塊裏。分片應該是根據業務的負載、根據數據的實時運行狀態,來決定這個數據應該放在哪兒。這是傳統的靜態分片不能相比的,無論傳統的用一致性哈希,仍是用最簡單的對機器數取模的方式去分片(都是不能比的)。
在這個架構下,甚至將來咱們還能讓 AI 來幫忙。把分片操做放到 PD 裏面,它就像一個 DBA 同樣,甚至預測 Workload 給出數據分佈操做。好比課程報名數據庫系統,系統發現可能明天會是報名高峯,就事先把數據給切分好,放到更好的機器上。這在傳統方案下是都須要人肉操做,其實這些事情都應該是自動化的。
Dynamic Data placement 好處首先是讓事情變得更 flexible ,對業務能實時感知和響應。另外還有一點,爲何咱們有了 Dynamic Placement 的策略,還要去作 Table Partition(今天上午申礫也提到了)?Table Partition 在背後實現其實挺簡單的。至關於業務這邊已經告訴咱們數據應該怎麼分片比較好,咱們還能夠作更多針對性的優化。這個 Partition 指的是邏輯上的 Partition ,是可能根據你的業務相關的,好比說我這張表,就是存着 2018 年的數據,雖然我在底下仍是 TiDB 這邊,經過 PD 去調度,可是我知道你 Drop 這個 Table 的時候,必定是 Drop 這些數據,因此這樣會更好,並且更加符合用戶的直覺。
但這樣架構仍然有比較大的挑戰。固然這個挑戰在靜態分片的模型上也都會有。好比說圍繞着這個問題,咱們一直在去嘗試解決怎麼更快的發現數據的熱點,好比說咱們的調度器,若是最好能作到,好比忽然來個秒殺業務,咱們立刻就發現了,就趕忙把這塊數據挪到好的機器上,或者把這塊數據趕忙添加副本,再或者把它放到內存的存儲引擎裏。這個事情應該是由數據庫自己去作的。因此爲何咱們這麼期待 AI 技術可以幫咱們,是由於雖然在 TiDB 內部,用了不少規則和方法來去作這個事情,但咱們不是萬能的。
還有大的趨勢是存儲計算分離。我以爲如今業界有一個特別大的問題,就是把存儲計算分離給固化成了某一個架構的特定一個指代,好比說只有長的像 Aurora 那樣的架構纔是存儲計算分離。那麼 TiDB 算存儲計算分離嗎?我以爲其實算。或者說存儲計算分離本質上帶來的好處是什麼?就是咱們的存儲依賴的物理資源,跟計算所依賴的物理資源並不同。這點其實很重要。就用 TiDB 來舉例子,好比計算可能須要不少 CPU,須要不少內存來去作聚合,存儲節點可能須要不少的磁盤和 I/O,若是全都放在一個組件裏 ,調度器就會很難受:我到底要把這個節點做爲存儲節點仍是計算節點?其實在這塊,可讓調度器根據不一樣的機型(來作決定),是計算型機型就放計算節點,是存儲型機型就放存儲節點。
今天因爲時間關係沒有給你們演示的插件平臺。將來 TiDB 會變成一個更加靈活的框架,像圖 20 中 TiFlash 是一個 local storage,咱們其實也在祕密研發一個新的存儲的項目叫 Unitstore,可能明年的 DevCon 就能看到它的 Demo 了。在計算方面,每一層咱們將來都會去對外暴露一個很是抽象的接口,可以去 leverage 不一樣的系統的好處。今年我其實很喜歡的一篇 Paper 是 F1 Query 這篇論文,基本表述了我對一個大規模的分佈式系統的期待,架構的切分很是漂亮。
說到分佈式事務,我也分享一下個人觀點。目前看上去,ACID 事務確定是必要的。咱們仍然尚未太多更好的辦法,除了 Google 在這塊用了原子鐘,Truetime 很是牛,咱們也在研究各類新型的時鐘的技術,可是要把它推廣到整個開源社區也不太可能。固然,時間戳,無論是用硬件仍是軟件分配,仍然是咱們如今能擁有最好的東西, 由於若是要擺脫中心事務管理器,時間戳仍是很重要的。因此在這方面的挑戰就會變成:怎麼去減小兩階段提交帶來的網絡的 round-trips?或者若是有一個時鐘的 PD 服務,怎麼能儘量的少去拿時間戳?
咱們在這方面的理論上有一些突破,咱們把 Percolator 模型作了一些優化,可以在數學上證實,能夠少拿一次時鐘。雖然咱們目前尚未在 TiDB 裏去實現,可是咱們已經把數學證實的過程已經開源出來了,咱們用了 TLA+ 這個數學工具去作了證實。此外在 PD 方面,咱們也在思考是否是全部的事務都必須跑到 PD 去拿時間戳?其實也不必定,咱們在這上面也已有一些想法和探索,可是如今尚未成型,這個不劇透了。另外我以爲還有一個很是重要的東西,就是 Follower Read。不少場景讀多寫少,讀的業務壓力不少時候是要比寫大不少的,Follower Read 可以幫咱們線性擴展讀的性能,並且在咱們的模型上,由於沒有時間戳 ,因此可以在一些特定狀況下保證不會去犧牲一致性。
另一點就是 Cloud-Native。剛剛中午有一個社區小夥伴問我,大家爲何不把多租戶作在 TiDB 的系統內部?**我想說「數據庫就是數據庫」,它並非一個操做系統,不是一個容器管理平臺。咱們更喜歡模塊和結構化更清晰的一個作事方式。**並且 Kubernetes 在這塊已經作的足夠好了 ,我相信將來 K8s 會變成集羣的新操做系統,會變成一個 Linux。好比說若是你單機時代作一個數據庫,你會在你的數據庫裏面內置一個操做系統嗎?確定不會。因此這個模塊抽象的邊界,在這塊我仍是比較相信 K8s 的。《Large-scale cluster management at Google with Borg》這篇論文裏面提到了一句話,BigTable 其實也跑在 Borg 上。
固然最後,你們聽完這一堆東西之後,回頭看咱們社區小夥伴們的願望列表(圖 24),就會發現對一下 TiDB 好像還都能對得上 :D
謝謝你們。
1 月 19 日 TiDB DevCon 2019 在北京圓滿落幕,超過 750 位熱情的社區夥伴參加了這次大會。會上咱們首次全面展現了全新存儲引擎 Titan、新生態工具 TiFlash 以及 TiDB 在雲上的進展,同時宣佈 TiDB-Lightning Toolset & TiDB-DM 兩大生態工具開源,並分享了 TiDB 3.0 的特性與將來規劃,描述了咱們眼中將來數據庫的模樣。此外,更有 11 位來自一線的 TiDB 用戶爲你們分享了實踐經驗與踩過的「坑」。同時,咱們也爲新晉 TiDB Committer 授予了證書,併爲 2018 年最佳社區貢獻我的、最佳社區貢獻團隊頒發了榮譽獎盃。