摘要:本文為我司申礫在上的演講實錄。雖然這個線程做的事情已經足夠簡單,但是因為上所有的都會通過一個線程來驅動自己的狀態機,所以當壓力足夠大的時候就會成為瓶頸。
本文為我司 Engineering VP 申礫在 TiDB DevCon 2019 上的演講實錄。在?上篇?中,申礫老師重點回顧了 TiDB 2.1 的特性,并分享了我們對「如何做好一個數據庫」的看法。TiDB 3.0 Beta
本篇將繼續介紹 TiDB 3.0 Beta 在穩定性、易用性、功能性上的提升,以及接下來在 Storage Layer 和 SQL Layer 的規劃,enjoy~
2018 年年底我們開了一次用戶吐槽大會,當時我們請了三個 TiDB 的重度用戶,都是在生產環境有 10 套以上 TiDB 集群的用戶。那次大會規則是大家不能講 TiDB 的優點,只能講缺點;研發同學要直面問題,不能辯解,直接提解決方案;當然我們也保護用戶的安全(開個玩笑 :D),讓他們放心的來吐槽。剛剛的社區實踐分享也有點像吐槽大會第二季,我們也希望用戶來提問題,分享他們在使用過程遇到什么坑,因為只有直面這些問題,才有可能改進。所以我們在 TiDB 3.0 Beta 中有了很多改進,當然還有一些會在后續版本中去改進。
1. Stability at ScaleTiDB 3.0 版本第一個目標就是「更穩定」,特別是在大規模集群、高負載的情況下保持穩定。穩定性壓倒一切,如果你不穩定,用戶擔驚受怕,業務時斷時續,后面的功能都是沒有用的。所以我們希望「先把事情做對,再做快」。
1.1 Multi-thread RaftStore首先來看 TiDB 3.0 一個比較亮眼的功能——多線程 Raft。我來給大家詳細解釋一下,為什么要做這個事情,為什么我們以前不做這個事情。
這是 TiKV 一個抽象的架構(圖 8)。中間標紅的圖形是 RaftStore 模塊,所有的 Raft Group 都在一個 TiKV 實例上,所有 Raft 狀態機的驅動都是由一個叫做 RaftStore 的線程來做的,這個線程會驅動 Raft 狀態機,并且將 Raft Log Append 到磁盤上,剩下的包括發消息給其他 TiKV 節點以及 Apply Raft Log 到狀態機里面,都是由其他線程來做的。早期的時候,可能用戶的數據量沒那么大,或者吞吐表現不大的時候,其實是感知不到的。但是當吞吐量或者數據量大到一定程度,就會感覺到這里其實是一個瓶頸。雖然這個線程做的事情已經足夠簡單,但是因為 TiKV 上所有的 Raft Peer 都會通過一個線程來驅動自己的 Raft 狀態機,所以當壓力足夠大的時候就會成為瓶頸。用戶會看到整個 TiKV 的 CPU 并沒有用滿,但是為什么吞吐打不上去了?
因此在 TiDB 3.0 中做了一個比較大的改進,就是將 RaftStore 這個線程,由一個線程變成一個線程池, TiKV 上所有 Raft Peer 的 Raft 狀態機驅動都由線程池來做,這樣就能夠充分利用 CPU,充分利用多核,在 Region 特別多以及寫入量特別大的時候,依然能線性的提升吞吐。
通過上圖大家可以看到,隨著并發不斷加大,寫入是能夠去線性擴展的。在早期版本中,并發到一定程度的時候,RaftStore 也會成為瓶頸,那么為什么我們之前沒有做這個事情?這個優化效果這么明顯,之所以之前沒有做,是因為之前 Raft 這塊很多時候不會成為瓶頸,而在其他地方會成為瓶頸,比如說 RocksDB 的寫入或者 gRPC 可能會成為瓶頸,然后我們將 RaftStore 中的功能不斷的向外拆,拆到其他線程中,或者是其他線程里面做多線程,做異步等等,隨著我們的優化不斷深入,用戶場景下的數據量、吞吐量不斷加大,我們發現 RaftStore 線程已經成為需要優化的一個點,所以我們在 3.0 中做了這個事情。而且之前保持單線程也是因為單線程簡單,「先把事情做對,然后再做快」。
1.2 Batch Message第二個改進是 Batch Message。我們的組件之間通訊選擇了 gRPC,首先是因為 gRPC 是 Google 出品,有人在維護他,第二是用起來很簡單,也有很多功能(如流控、加密)可以用。但其實很多人吐嘈它性能比較慢,在知乎上大家也能看到各種問題,包括討論怎么去優化他,很多人也有各種優化經驗,我們也一直想怎么去優化他。以前我們用的方法是來一個 message 就通過 gRPC 發出去,雖然性能可能沒有那么好,或者說性能不是他最大的亮點,但有時候調性能不能單從一個模塊去考慮,應該從架構上去想,就是架構需要為性能而設計,架構上的改進往往能帶來性能的質變。
所以我們在 TiDB 3.0 Beta 中設計了 Batch Message 。以前是一個一個消息的發,現在是按照消息的目標分隊列,每個隊列會有一個 Timer,當消息湊到一定個數,或者是你的 Timer 到了時間(現在應該設置的是 1ms,Batch 和這個 Timer 數量都可以調),才會將發給同一個目的地的一組消息,打成一個包,一起發過去。有了這個架構上的調整之后,我們就獲得了性能上的提升。
當然大家會想,會不會在并發比較低的時候變慢了?因為你湊不到足夠的消息,那你就要等 Timer。其實是不會的,我們也做了一些設計,就是由對端先匯報「我當前是否忙」,如果對端不忙,那么選擇一條一條的發,如果對端忙,那就可以一個 Batch 一個 Batch 的發,這是一個自適應的 Batch Message 的一套系統。圖 11 右半部分是一個性能對比圖,有了 Batch Message 之后,在高并發情況下吞吐提升非常快,在低并發情況下性能并沒有下降。相信這個改進可以給大家帶來很大的好處。
1.3 Titan第三點改進就是 Titan。CEO 劉奇在 Opening Keynote 中提到了我們新一代存儲引擎 Titan,我們計劃用 Titan 替換掉 RocksDB,TiDB 3.0 中已經內置了 Titan,但沒有默認打開,如果大家想體驗的話,可以通過配置文件去把 RocksDB 改成 Titan。我們為什么想改進 RocksDB 呢?是因為它在存儲大的 Key Value 的時候,有存儲空間放大和寫放大嚴重的問題。
所以我們嘗試解決這個問題。當你寫入的 Key Value 比較大的時候,我們會做一個檢查,然后把大的 Value 放到一個 Blob File 里去,而不是放到 LSM-Tree。這樣的分開存儲會讓 LSM-Tree 變得很小,避免了因為 LSM-Tree 比較高的時候,特別是數據量比較大時出現的比較嚴重的寫放大問題。有了 Titan 之后,就可以解決「單個 TiKV 服務大量數據」的需求,因為之前建議 TiKV 一個實例不要高于 1T。我們后面計劃單個 TiKV 實例能夠支持 2T 甚至 4T 數據,讓大家能夠節省存儲成本,并且能在 Key Value 比較大的時候,依然能獲得比較好的性能。
除了解決寫放大問題之外,其實還有一個好處就是我們可以加一個新的 API,比如 KeyExist,用來檢查 Key 是否存在,因為這時 Key 和 Value 是分開存儲的,我們只需要檢查 Key 是否在,不需要把 Value Load 進去。或者做 Unique Key 檢查時,可以不需要把 Key Value 取出來,只需要加個接口,看這個 Key 是否存在就好了,這樣能夠很好的提升性能。
1.4 Robust Access Path Selection第四點是保持查詢計劃穩定。這個在數據庫領域其實是一個非常難的問題,我們依然沒有 100% 解決這個問題,希望在 2019 年第一季度,最多到第二季度,能有一個非常好的解決方案。我們不希望當數據量變化 、寫入變化、負載變化,查詢計劃突然變錯,這個問題在線上使用過程中是災難。那么為什么會跑著跑著變錯?首先來說我們現在是一個 Cost-based optimizers,我們會參考統計信息和當前的數據的分布,來選擇后面的 plan。那么數據的分布是如何獲得的呢?我們是通過統計信息,比如直方圖、CM Sketch來獲取,這里就會出現兩個問題:
1. 統計信息可能是不準的。統計信息畢竟是一個采樣,不是全量數據,會有一些數據壓縮,也會有精度上的損失。
2. 隨著數據不斷寫入,統計信息可能會落后。因為我們很難 100% 保證統計信息和數據是 Match 的。
一個非常通用的思路是, 除了依賴于 Cost Model 之外,我們還要依賴更多的 Hint,依賴于更多啟發式規則去做 Access Path 裁減。舉個例子:
select * from t where a = x and b = y; idx1(a, b) idx2(b) -- pruned
大家通過直觀印象來看,我們一定會選擇第一個索引,而不是第二個索引,那么我們就可以把第二個索引裁掉,而不是因為統計信息落后了,然后估算出第二個索引的代價比較低,然后選擇第二個索引。上面就是我們最近在做的一個事情,這里只舉了一個簡單的例子。
2. UsabilityTiDB 3.0 第二個目標是可用性,是讓 TiDB 簡單易用。
2.1 Query Tracing在 TiDB 2.0 中,大家看一個 Query 為什么慢了依賴的是 Explain,就是看查詢計劃,其實那個時候大家很多都看不懂,有時候看了也不知道哪有問題。后來我們在 TiDB 2.1 中支持了 Explain Analyze,這是從 PG ?借鑒過來一個特性,就是我們真正的把它執行一邊,然后再看看每個算子的耗時、處理的數據量,看看它到底干了一些什么事情,但其實可能還不夠細,因為還沒有細化到算子內部的各種操作的耗時。
所以我們又做了一個叫 Query Tracing 的東西,其實在 TiDB 2.1 之前我們已經做了一部分,在 TiDB 3.0 Beta 中做了一個收尾,就是我們可以將 Explain 結果轉成一種 Tracing 格式,再通過圖形化界面,把這個 Tracing 的內容展示出來,就可以看到這個算子具體干了一些什么事,每一步的消耗到底在哪里,這樣就可以知道哪里有問題了。希望大家都能在 TiDB 3.0 的版本中非常直觀的定位到 Query 慢的原因。
2.2 Plan Management然后第二點 Plan Management 其實也是為了 Plan 不穩定這個問題做準備的。雖然我們希望數據庫能自己 100% 把 Plan 選對,但是這個是非常美好的愿望,應該還沒有任何一個數據庫能保證自己能 100% 的解決這個問題。那么在以前的版本中,出現問題怎么辦?一種是去 Analyze 一下,很多情況下他會變好,或者說你打開自動 Analyze 這個特性,或者自動 FeedBack 這個特性,可以一定程度上變好,但是還可能過一陣統計信息又落后了,又不準了,Plan 又錯了,或者由于現在 cost 模型的問題,有一些 Corner Case 處理不到,導致即使統計信息是準確的, Plan 也選不對。
那么我們就需要一個兜底方案,讓大家遇到這個問題時不要束手無策。一種方法是讓業務去改 SQL,去加 Hint,也是可以解決的,但是跟業務去溝通可能會增加他們的使用成本或者反饋周期很長,也有可能業務本身也不愿意做這個事情。
另外一種是用一種在線的方式,讓數據庫的使用者 DBA 也能非常簡單給這個 Plan 加 Hint。具體怎么做呢?我們和美團的同學一起做了一個非常好的特性叫 Plan Management,就是我們有一個 Plan 管理的模塊,我們可以通過 SQL 接口給某一條 Query,某一個 Query 綁定 Plan,綁定 Hint,這時我們會對 SQL 做指紋(把 Where 條件中的一些常量變成一個通配符,然后計算出一個 SQL 的指紋),然后把這個 Hint 綁定在指紋上。一條 Query 來了之后,先解成 AST,我們再生成指紋,拿到指紋之后,Plan Hint Manager 會解析出綁定的 Plan 和 Hint,有 Plan 和 Hint 之后,我們會把 AST 中的一部分節點替換掉,接下來這個 AST 就是一個「帶 Hint 的 AST」,然后扔給 Optimizer,Optimizer 就能根據 Hint 介入查詢優化器以及執行計劃。如果出現慢的 Query,那么可以直接通過前面的 Query Tracing 去定位,再通過 Plan Management 機制在線的給數據庫手動加 Hint,來解決慢 Query 的問題。這樣下來也就不需要業務人員去改 SQL。這個特性應該在 TiDB 3.0 GA 正式對外提供,現在在內部已經跑得非常好了。在這里也非常感謝美團數據庫開發同學的貢獻。
2.3 Join ReorderTiDB 3.0 中我們增加了 Join Reorder。以前我們有一個非常簡單的 Reorder 算法,就是根據 Join 這個路徑上的等值條件做了一個優先選擇,現在 TiDB 3.0 Beta 已經提供了第一種 Join Reorder 算法,就是一個貪心的算法。簡單來說,就是我有幾個需要 Join 的表,那我先從中選擇 Join 之后數據量最小的那個表(是真正根據 Join 之后的代價來選的),然后我在剩下的表中再選一個,和這個再組成一個 Join Path,這樣我們就能一定程度上解決很多 Join 的問題。比如 TPC-H 上的 Q5 以前是需要手動加 Hint 才能跑出來,因為它沒有選對 Join 的路徑,但在 TiDB 3.0 Beta 中,已經能夠自動的選擇最好的 Join Path 解決這個問題了。
我們接下來還要再做一個基于動態規劃的 Join Reorder 算法,很有可能會在 3.0 GA 中對外提供。 在 Join 表比較少的時候,我們用動態規劃算法能保證找到最好的一個 Join 的路徑,但是如果表非常多,比如大于十幾個表,那可能會選擇貪心的算法,因為 Join Reorder 還是比較耗時的。
3. Functionality說完穩定性和易用性之外,我們再看一下功能。
我們現在做了一個插件系統,因為我們發現數據庫能做的功能太多了,只有我們來做其實不太可能,而且每個用戶有不一樣的需求,比如說這家想要一個能夠結合他們的監控系統的一個模塊,那家想要一個能夠結合他們的認證系統做一個模塊,所以我們希望有一個擴展的機制,讓大家都有機會能夠在一個通用的數據庫內核上去定制自己想要的特性。這個插件是基于 Golang 的 Plugin 系統。如果大家有 TiDB Server 的 Binary 和自己插件的 .so,就能在啟動 TiDB Server 時加載自己的插件,獲得自己定制的功能。
圖 17 還列舉了一些我們正在做的功能,比如白名單,審計日志,Slow Query,還有一些在 TiDB Hackathon 中誕生的項目,我們也想拿到插件中看看是否能夠做出來。
4. Performance從圖 18 中可以看到,我們對 TiDB 3.0 Beta 中做了這么多性能優化之后,在 OLTP 這塊進步還是比較大的,比如在 SysBench 下,無論是純讀取還是寫入,還是讀加寫,都有幾倍的提升。在解決穩定性這個問題之后,我們在性能方面會投入更多的精力。因為很多時候不能把「性能」單純的當作性能來看,很多時候慢了,可能業務就掛了,慢了就是錯誤。
當然 TiDB 3.0 中還有其他重要特性,這里就不詳細展開了。(TiDB 3.0 Beta Release Notes?)
Next?剛才介紹是 3.0 Beta 一些比較核心的特性,我們還在繼續做更多的特性。
1. Storage Layer比如在存儲引擎層,我們對 Raft 層還在改進,比如說剛才我提到了我們有 Raft Learner,我們已經能夠極大的減少由于調度帶來的 Raft Group 不可用的概率,但是把一個 Learner 提成 Voter 再把另一個 Voter 干掉的時間間隔雖然比較短,但時間間隔依然存在,所以也并不是一個 100% 安全的方案。因此我們做了 Raft Joint Consensus。以前成員變更只能一個一個來:先把 Learner 提成 Voter,再把另一個 Voter 干掉。但有了 Raft Joint Consensus 之后,就能在一次操作中執行多個 ConfChange,從而把因為調度導致的 Region 不可用的概率降為零。
另外我們還在做跨數據中心的部署。前面社區實踐分享中來自北京銀行的于振華老師提到過,他們是一個兩地三中心五部分的方案。現在的 TiDB 已經有一些機制能比較不錯地處理這種場景,但我們能夠做更多更好的東西,比如說我們可以支持 Witness 這種角色,它只做投票,不同步數據,對帶寬的需求比較少,即使機房之間帶寬非常低,他可以參與投票。在其他節點失效的情況下,他可以參與選舉,決定誰是 Leader。另外我們支持通過 Follower 去讀數據,但寫入還是要走 Leader,這樣對跨機房有什么好處呢? 就是可以讀本地機房的副本,而不是一定要讀遠端機房那個 Leader,但是寫入還是要走遠端機房的 Leader,這就能極大的降低讀的延遲。除此之外,還有支持鏈式復制,而不是都通過 Leader 去復制,直接通過本地機房復制數據。
之后我們還可以基于 Learner 做數據的 Backup。通過 learner 去拉一個鏡像,存到本地,或者通過 Learner 拉取鏡像之后的增量,做增量的物理備份。所以之后要做物理備份是通過 Learner 實時的把 TiKV 中數據做一個物理備份,包括全量和增量。當需要恢復的時候,再通過這個備份直接恢復就好了,不需要通過 SQL 導出再導入,能比較快提升恢復速度。
2. SQL Layer在 SQL 層,我們還做了很多事情,比如?Optimizer 正在朝下一代做演進,它是基于最先進的 Cascades 模型。我們希望 Optimizer 能夠處理任意復雜的 Query,幫大家解決從 OLTP 到 OLAP 一整套問題,甚至更復雜的問題。比如現在 TiDB 只在 TiKV 上查數據,下一步還要接入TiFlash,TiFlash 的代價或者算子其實不一樣的,我們希望能夠在 TiDB 上支持多個存儲引擎,比如同一個 Query,可以一部分算子推到 TiFlash 上去處理,一部分算子在 TiKV 上處理,在 TiFlash 上做全表掃描,TiKV 上就做 Index 點查,最后匯總在一起再做計算。
我們還計劃提供一個新的工具,叫?SQL Tuning Advisor。現在用戶遇到了慢 Query,或者想在上線業務之前做 SQL 審核和優化建議,很多時候是人肉來做的,之后我們希望把這個過程變成自動的。
除此之外我們還將支持向量化的引擎,就是把這個引擎進一步做向量化。未來我們還要繼續兼容最新的 MySQL 8.0 的特性 Common Table,目前計劃以 MySQL 5.7 為兼容目標,和社區用戶一起把 TiDB 過渡到 MySQL 8.0 兼容。
說了這么多,我個人覺得,我們做一個好的數據庫,有用的數據庫,最重要一點是我們有大量的老師,可以向用戶,向社區學習。不管是分享了使用 TiDB 的經驗和坑也好,還是去提 Issue 報 Bug,或者是給 TiDB 提交了代碼,都是在幫助我們把 TiDB 做得更好,所以在這里表示一下衷心的感謝。最后再立一個 flag,去年我們共寫了 24 篇 TiDB 源碼閱讀文章,今年還會寫?TiKV 源碼系列文章。我們希望把項目背后只有開發同學才能理解的這套邏輯講出來,讓大家知道 TiDB 是怎樣的工作的,希望今年能把這個事情做完,感謝大家。
1 月 19 日 TiDB DevCon 2019 在北京圓滿落幕,超過 750 位熱情的社區伙伴參加了此次大會。會上我們首次全面展示了全新存儲引擎 Titan、新生態工具 TiFlash 以及 TiDB 在云上的進展,同時宣布 TiDB-Lightning Toolset & TiDB-DM 兩大生態工具開源,并分享了 TiDB 3.0 的特性與未來規劃,描述了我們眼中未來數據庫的模樣。此外,更有 11 位來自一線的 TiDB 用戶為大家分享了實踐經驗與踩過的「坑」。同時,我們也為新晉 TiDB Committer 授予了證書,并為 2018 年最佳社區貢獻個人、最佳社區貢獻團隊頒發了榮譽獎杯。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/17922.html
摘要:我司申礫在上分享了產品進化過程中的思考與未來規劃。第一點是對整個聚合框架做了優化,就是從一行一行處理的聚合模式,變成了一批一批數據處理的聚合模式,另外我們還在哈希聚合算子上做了并行。 我司 Engineering VP 申礫在 TiDB DevCon 2019 上分享了 TiDB 產品進化過程中的思考與未來規劃。本文為演講實錄上篇,重點回顧了 TiDB 2.1 的特性,并分享了我們對...
摘要:另外,我們為教職人員和在校學生提供學術優惠票價,僅限優惠碼注冊,申請材料教職人員校園網站個人信息頁截圖或教師資格證本人身份證掃描件在校學生本人有效學生證本人身份證掃描件請將申請材料發送到,審核結果將通過郵件通知。優惠碼申請截止時間月日。 年度最高規格的 TiDB 技術大會海內外動態及成果的綜合呈現最新核心技術解讀多個成果首次亮相2019 RoadMap 展望14 位海內外基礎架構領域技...
閱讀 2854·2021-09-28 09:36
閱讀 3955·2021-09-22 15:52
閱讀 3639·2021-09-06 15:00
閱讀 1959·2021-09-02 15:40
閱讀 2804·2021-09-02 15:15
閱讀 3470·2021-08-17 10:15
閱讀 2787·2019-08-30 15:53
閱讀 2079·2019-08-29 18:39