摘要:本文由紅鳳凰粉鳳凰粉紅鳳凰隊的成員主筆,他們的項目在本屆中獲得了二等獎。用戶在平臺上進行第一章部署的學習,了解到可以通過進行部署。收到事件后,更新。由于位置是由屬性給出的,因此為其加上,即可實
本文由紅鳳凰粉鳳凰粉紅鳳凰隊的成員主筆,他們的項目 TiDB Lab?在本屆 TiDB Hackathon 2018 中獲得了二等獎。TiDB Lab 為 TiDB 培訓體系增加了一個可以動態觀測 TiDB / TiKV / PD 細節的動畫教學 Lab,讓用戶可以一邊進行真實操作一邊觀察組件之間的變化,例如 SQL 的解析,Region 的變更等等,從而生動地理解 TiDB 的工作原理。項目簡介 簡介
TiDB Lab,全稱 TiDB Laboratory,是一個集 TiDB 集群狀態的在線實時可視化與交互式教學的平臺。用戶可以一邊對 TiDB 集群各個組件 TiKV、TiDB、PD 進行各種操作,包括上下線、啟動關閉、遷移數據、插入查詢數據等,一邊在 TiDB Lab 上以動畫形式觀察操作對集群的影響,例如數據是怎么流動的,Region 副本在什么情況下發生了變更等等。通過 TiDB Lab 這種對操作進行可視化反饋的交互模式,用戶可以快速且生動地理解 TiDB 內部原理。
功能實時動態展示 TiDB、TiKV 節點的新增、啟動與關閉。
實時動態展示 TiDB 收到 SQL 后,物理算子將具體請求發送給某些 TiKV Region Leader 并獲取數據的過程。
實時動態展示各個 TiKV 實例上 Region 副本狀態的變化,例如新增、刪除、分裂。
實時動態展示各個 TiKV 實例上 Region 副本內的數據量情況。
瀏覽集群事件歷史(事件指上述四條功能所展示的各項內容)并查看事件的詳細情況,包括事件的具體數據內容、SQL Plan 等等。
按 TiDB、TiKV 或 Region 過濾事件歷史。
對事件歷史進行時間穿梭:回到任意事件發生時刻重新觀察當時的集群狀態,或按事件單步重放觀察集群狀態的變化。
在線獲取常用運維操作的操作指南。
愿景我們其實為 TiDB Lab 規劃了更大的愿景,但由于 Hackathon 時間關系,還來不及實現。我們希望能實現 TiDB Lab + TiDB 生態組件的沙盒,從而在 TiDB Lab 在線平臺上直接提供命令執行與 SQL 執行功能。這樣用戶無需離開平臺,無需自行準備機器下載部署,就可以直接在平臺上根據提供的操作指南進行各類操作,并能觀察操作帶來的具體影響,形成操作與反饋的閉環,真正地實現零門檻瀏覽器在線教學。我們期望平臺能提供用戶以下的操作流程:
1. 用戶獲得一個 TiDB Lab 賬戶并登錄(考慮到沙盒是占用實際資源的,需要通過賬戶許可來限制避免資源快速耗盡)。
2. 用戶在 TiDB Lab 上獲得若干虛擬機器的訪問權限,每個機器處于同一內網并具有獨立 IP。這些虛擬機器的實際實現是資源受限的虛擬機或沙盒,因為作為教學實驗不需要占用很多資源。
例如:平臺為用戶自動分配了 5 個 IP 獨立的沙盒的訪問權限,地址為 192.168.0.1 ~ 192.168.0.5。
3. 用戶在平臺上進行第零章「架構原理」的學習。平臺提供了一個默認的拓撲部署,用戶可以在平臺提供的在線 SQL Shell 中進行數據的插入、刪除、更新等操作。用戶通過平臺觀察到 SQL 是如何對應到 TiKV 存儲節點上的,以及數據是怎么切分到不同 Region 的等等。
4. 用戶在平臺上進行第一章「TiDB 部署」的學習,了解到可以通過 ansible 進行部署。教學樣例是一個典型的 TiDB + TiKV 三副本部署。對于這個教學樣例,平臺告知用戶 inventory.ini 具體內容應當寫成什么樣子。用戶可以在平臺提供的在線 Terminal 上修改 inventory 文件,并執行部署與集群啟動命令。部署和啟動均能在平臺上實時反饋可視化。
5. 用戶繼續進行后續章節學習,例如「TiDB 單一服務啟動與關閉」。用戶在可視化界面上點擊某個剛才已經部署出來的節點,可以了解啟動或關閉單個 TiDB 的命令。用戶可以在平臺提供的在線 Terminal 上執行這些命令,嘗試啟動或關閉單一 TiDB。
6. 用戶繼續學習基礎運維操作,例如「TiKV 擴容」。平臺告知 inventory.ini 應當如何進行修改,用戶可以根據指南在在線 Terminal 上進行實踐,并通過可視化界面觀察擴容的過程,例如其他節點上的副本被逐漸搬遷到新節點上。
前期準備 團隊我們團隊有三個人,是一個 PingCAP 同學與 TiDB 社區小伙伴錢同學的混合組隊,其中 PingCAP 成員分別來自 TiKV 組與 OLAP 組。我們本著搞事情的想法,團隊取名叫「紅鳳凰粉鳳凰粉紅鳳凰」,想圍觀主持人念團隊名稱(然而機智的主持人小姐姐讓我們自報團隊名稱)。
原計劃:干掉 gRPC鑒于從報名開始直到 Hackathon 正式開始前幾小時,我們都在為原計劃做準備,因此值得詳細說一下…
我們一開始規劃的 Hackathon 項目是換掉 TiKV、TiDB 之間的 RPC 框架 gRPC,原因有幾個:
一是發現 TiKV、TiDB 中 gRPC 經常占用了大量 CPU,尤其是在請求較多但很簡單的 benchmark 場景中經常比 Coprocessor 這塊兒還高,這在客戶機器 CPU 資源比較少的情況下是性能瓶頸;
二是發現 gRPC 性能一般,在各類常用 RPC 框架的性能測試中 gRPC 經常是墊底水平;
三是 gRPC 主要設計用于用戶產品與 Google 服務進行通訊,因而考慮到了包括負載均衡友好、流量控制等方面,但對 TiKV 與 TiDB 這類內部通訊來說這些都是用不上的功能,為此犧牲的性能是無謂的開銷;
另外近期 TiKV 內部有一個實驗是將多個 RPC 請求 batch 到一起再發送(當然處理時候再拆開一個一個執行原來的 handler),性能可以瞬間提高一倍以上,這也從側面說明了 gRPC 框架自身開銷很大,因為用戶側請求總量是一致的,處理模式也是一致的,唯一的區別就是 RPC 框架批量發送或一條一條發送。
我們早在幾周前就開始寫簡單 Echo Server 進行可行性驗證和性能測試,是以下三個方面的正交:
1. 協議:CapnProto RPC、brpc over gRPC、裸寫 echo。
2. 服務端:Rust、C++,對應用于 TiKV。
3. 客戶端:Golang,對應用于 TiDB。
其中 TiKV 側調研了 Rust 和 C++ 的服務端實現,原因是 Rust 可以通過 binding 方式調用 C++ 服務端。而 TiDB 側客戶端實現不包含 C++ 的原因是 Golang 進行 C / C++ FFI 性能很差,因此可以直接放棄 C/C++ 包裝一層 binding 用于 TiDB 的想法。最后測試下來,有以下結果:
CapnProto:序列化性能很高,但其 RPC 性能沒有很突出。最重要的是,CapnProto 的 Golang Client 實現有 bug,并不能穩定地與 Rust 或 C++ 的 Server 進行 RPC 交互。作者回復說這是一個已知缺陷,涉及重構。這對于 Hackathon 來說是一個致命的問題,我們并沒有充足的時間解決這個問題,直接導致我們放棄這個方案。
brpc over gRPC:可以實現使用 brpc C++ 客戶端 & gRPC Golang 服務端配合(注:brpc 沒有 Golang 的實現)。但這個方案本質只是替換服務端的實現,并沒有替換協議,并不徹底,我們不是特別喜歡。另外在這個換湯不換藥的方案下,測試下來性能的提升有限,且隨著 payload 越大會越小。我們最終覺得作為一個 Hackathon 項目如果僅有有限的性能提升(雖然可以在展示的時候掩蓋缺陷只展示優點),那么意義不是很大,最終無法用于產品,因而放棄。
裸寫:我們三個成員都不是這方面的老司機,裸寫大概是寫不完的。。
新計劃:做一個用于培訓的可視化在 Hackathon 開始的前一個晚上,我們決定推翻重來,于是 brain storm 了幾個想法,最后覺得做一個用于教學的可視化比較可行,并且具有比較大的實際意義。另外,這個新項目「集群可視化」相比原項目「換 RPC」來說更適合 Hackathon,主要在于:
1. 具有圖形化界面,容易拿獎可以直觀地展現成果。
2. 并不是一個「非零即一」的任務。新項目有很多子功能,可以逐一進行實現,很穩妥,且不像老項目那樣只有換完才知道效果。
我們繼續在這個「可視化」的想法上進行了進一步的思考,想到如果可以做成在線教學的模式,則可以進一步擴展其項目意義,形成一個完整的在線教學體系,因此最終決定了項目的 scope。
具體實現在 TiKV、TiDB 與 PD 中各個關鍵路徑上將發生的具體「事件」記錄下來,并在前端進行一一可視化。事件
我們將 TiDB Lab 進行可視化所需要的信號稱為「事件」,并規劃了以下「事件」:
Ansible 事件:Ansible 部署 TiDB
Ansible 事件:Ansible 部署 TiKV
TiDB 事件:TiDB 啟動
TiDB 事件:TiDB 關閉
TiDB 事件:TiDB 收到一條 SQL
TiKV 事件:TiKV 啟動
TiKV 事件:TiKV 關閉
TiKV 事件:TiKV 收到一條 KvGet 請求
TiKV 事件:TiKV 收到一條 PreWrite / Commit 請求
TiKV 事件:TiKV 收到一條 Coprocessor 請求
TiKV 事件:TiKV Region Peer 創建
TiKV 事件:TiKV Region Peer 刪除
TiKV 事件:TiKV Region 分裂
TiKV 事件:TiKV Region Snapshot 復制
TiKV 事件:TiKV Region 數據量發生顯著變化
最后,由于時間關系、技術難度和可視化需要,實際實現的是以下事件:
TiDB 事件:TiDB 啟動,若首次啟動認為是新部署
TiDB 事件:TiDB 關閉
TiDB 事件:TiDB 收到 SQL 并發起 KvGet 讀請求
TiDB 事件:TiDB 收到 SQL 并發起 PreWrite / Commit 寫入請求
TiDB 事件:TiDB 收到 SQL 并發起 Coprocessor 讀請求
TiKV 事件:TiKV 啟動,若首次啟動認為是新部署
TiKV 事件:TiKV 關閉
PD 事件:TiKV Region Peer 創建(通過 Region 心跳實現)
PD 事件:TiKV Region Peer 刪除(通過 Region 心跳實現)
PD 事件:TiKV Region 分裂(通過 Region 心跳實現)
PD 事件:TiKV Region 數據量發生顯著變化(通過 Region 心跳實現)
可視化可視化部分由前端(lab-frontend)和事件收集服務(lab-gateway)組成。
事件收集服務是一個簡單的 HTTP Server,各個組件通過 HTTP Post 方式告知事件,事件收集服務將其通過 WebSocket 協議實時發送給前端。事件收集服務非常簡單,使用的是 Node.js 開發,基于 ExpressJs 啟動 HTTP Server 并基于 SocketIO 實現與瀏覽器的實時通訊。ExpressJs 收到事件 JSON 后將其通過 SocketIO 進行廣播,總代碼僅僅十幾行。
可視化前端采用 Vue 實現,動畫使用 animejs 和 CSS3。
通過模板實現的可視化
一部分事件通過「由事件更新集群狀態數據 – 由集群狀態通過 Vue 渲染模板」進行可視化。
這類可視化是最簡單的,以 TiDB 啟動與否為例,TiDB 的啟動與否在界面上呈現為一個標簽顯示為「Started」或「Stopped」,那么就是一個傳統的 Vue MVVM 流程:
1. 數據變量 instances.x.online 代表 TiDB x 是否已啟動。
2. 收到 TiDB Started 事件后,更新 instances.x.online = true 。
3. 收到 TiDB Stopped 事件后,更新 instances.x.online = false 。
4. 前端模板上,根據 instances.x.online 渲染成 Started 或 Stopped 對應的界面。
這類可視化的動畫采用的是 CSS3 動畫。由于 Region Peer 位置是由 left, top CSS 屬性給出的,因此為其加上 transition,即可實現 Region Peer 在屏幕上顯示的位置改變的動畫。位置改變會主要發生在分裂時,分裂時 Region 列表中按順序會新增一個,那么后面各個 Region 都要向后移動(或換到下一行等)。
最后,使用 Vue Group Transition 功能,即可為 Region Peer 的新增與刪除也加入動畫效果。
通過動畫實現的可視化
另一部分事件并不反應為一個持久化 DOM 的變化,例如 TiDB 收到 SQL 并發請求到某個具體 TiKV 上 Region peer 的事件,在前端展示為一個 TiDB 節點到 TiKV Region Peer 的過渡動畫。動畫開始前和動畫結束后,DOM 沒有什么變化,動畫是一個臨時的可視元素。這類動畫通過 animejs 實現。
時間穿梭
時間穿梭是一個在目前前端框架中提供的很時髦的功能,我們準備借鑒一波。主要包括:1. 回退到任意一個歷史事件發生的時刻展示集群的狀態;2. 從當前事件開始往后進行單步可視化重現。
時間穿梭的本質是需要實現兩個基礎操作:
1. 對于單一事件實現正向執行,即事件發生后,更新對應集群數據信息(如果采用「通過模板實現的可視化」),或創建臨時動畫 DOM(如果采用「通過動畫實現的可視化」)。另外允許跳過「通過動畫實現的可視化」這一步。
2. 對于單一事件實現反向執行,即撤銷這個事件造成的影響。對于「通過模板實現的可視化」,我們需要根據事件內容反向撤銷它對集群數據信息的修改。對于「通過動畫實現的可視化」,我們什么都不用做。
時間穿梭的功能可以通過組合這兩個基礎操作實現。
1. 回退到任意歷史事件發生時刻:若想要前往的事件早于當前呈現的事件,則對于這期間的事件逐一進行反向執行。若想要前往的事件晚于當前呈現的事件,則進行無動畫的正向執行。
2. 從當前事件開始單步可視化:執行一次有動畫的正向執行。
3. 實時展示新事件:執行一次有動畫的正向執行。
TiDB 事件收集TiDB 的歷史事件收集略為 Hack。由于需要過濾任何非用戶發起的查詢(類似 GC 或者 meta 查詢會由背景協程頻繁發起打擾使用體驗),因此在用戶鏈接入口處添加了 context 標記一路攜帶到執行層,再修改相應的協程同步數據結構添加需要轉發的標記信息。比較麻煩的是類似 Point Get 這樣接口允許攜帶信息非常少的調用,只好將標記位編碼進 Key 本身了。Plan 的可視化其實并沒有花多少功夫,因為找到 TiDB 本身已經做了類似的功能,我們無非只是將這塊代碼直接偷來了。
PD 事件收集原本不少事件希望在 TiKV 端完成偵聽,不過顯然 KV 一小時編譯一次的效率無法滿足 Hackathon 中多次試錯的需要。因此我們改為在 PD 中偵測心跳和匯報事件。其實并沒有什么神秘,在原本 PD 自己檢查 Region 變更的代碼拆分成 Region 和 Peer 變更:每次 PD 接到 Region 心跳會在 PD Cache 中進行 Version 和 confVer 變更的檢測,主要涉及 Peer 的增加和減少等。而 Region Split 會多帶帶由 RegionSplitReport 進行匯報,這里也會做一次 Hook。另外就是每次心跳會檢查是否有未上報給 Lab 的 Region 信息,如果有就轉換成 Peer 信息進行補發。
TiKV 事件收集如上,原本我們計劃了很多 TiKV 事件,但由于開發機器配置不佳,每次修改都要等待一小時進行一次編譯,考慮到 Hackathon 上時間緊迫,因此最終大大縮減了 TiKV 上收集的事件數量,改為只收集啟動和停止。基本架構是事件發生的時候,事件異步發送給一個 Channel,Channel 的另一端有一個異步的 worker 負責不斷處理各個事件并通過 Hyper HTTP Client 發送出去。這個流程其實與 TiKV 中匯報 PD 事件有些類似,只是事件內容和匯報目標不一樣。
感悟以下文字 by 馬曉宇 @ OLAP Team, PingCAP
“由于比較能調侃干的活相對少一些,所以大王要我來巡山寫感悟。”
就像隊長說的,這個項目原本是希望做一個 bRPC 替換 gRPC 的試驗,只是由于種種原因臨到 Hackathon 前夜我們才確定這是個大概率翻車的點子。于是乎我們只好在酒店里抓耳撓腮,一邊討論可能的補救措施。
參加過、圍觀過幾次 Hackathon,見過現場 Demo 效果最震撼的一次其實并不是一個技術上最優秀的作品,但是它的確贏得了大獎。那是一個腦洞奇大的點子:用 Kinect 體感加上 DirectX 的全 3D 展示做的網絡流量實時展示;程序根據實時數據(舉辦方提供了實時網絡測量統計信息)聚合顯示不同粗細的炫酷弧光特效,而演示者則用手勢操控地球模型的旋轉。
于是在完全不了解大家是否能搞定前端的情況下,我們還是很輕率地決定了要做個重前端的項目。至于展示什么?既然時間不夠,那么秀一個需要生產上線的可視化工具,翻車的概率就大的多,不如直接定位為 For Educational Purpose Only。而且大概是過度解讀了炫酷對于成功的重要性,因此隊長也輕率地決定了這個項目的基調是「極盡浮夸」。就在這樣友好且不靠譜的討論氛圍下,這個項目的策劃出爐了。
之后就是艱苦卓絕連綿無休的代碼過程了。
龍毛二哥,曉峰和胡家屬的?TiNiuB Team?就在我們對面開工。講道理這其實是我個人最喜歡的項目之一。第一天放學的時候,看著他們的進度其實我心里虛得不行:看看別人家的項目,我們的絕對主力還在折騰 TiDB Logo 動畫,是我敢怒不敢言的狀態。
原來我想偷一下懶回家睡個覺啥的,就臨時改變主意繼續配合隊長努力干活;錢同學也抱著「TiKV 一天只能 Build 24 次必須珍惜」的態度寫著人生的第一個 Rust 項目。
因此,這里必須鳴謝龍哥他們對我們的鞭策。
事實證明,誤打誤撞但又深謀遠慮的浮夸戰略是有效的。Demo 的時候我很認真地盯著評委:在本項目最浮夸的 Logo 展示環節,大家的眼睛是發著光的,一如目睹了摩西分開紅海。我個人認為這個動畫 Logo 生生拉高了項目 50% 的評分。
只是具體要說感悟的話(似乎好多年沒寫感悟了呢),首先這次我們三個組員雖然有兩個是 PingCAP 員工,不過由于技能的缺口大于人力,因此負責的任務都不是自己所屬的模塊:隊長是 TiKV 組的但是在寫前端,我是 OLAP 組的但是在改 PD 和 DB,錢同學也在做自己從來沒寫過的 Rust(參賽前一周簡單入門了一下),因此其實還蠻有挑戰的(笑)。然后偶爾寫寫自己不熟悉的語言,搞搞自己不熟悉的模塊,會有一種別樣的新鮮刺激感,這大概就是所謂的路邊野花更香吧(嗯)?除此之外,Hackathon 更像一個大型社交活動,滿足了貓一樣孤僻的程序員群體被隱藏的社交欲,有利于碼農的身心發展,因此可以多搞搞 :) 。
回到我們項目本身的話,其實 TiDB 的源碼閱讀或者其他介紹類文章其實并不能非常直觀地幫助一頭霧水的初學者理解這個系統。我們做這個項目的最大目的是能降低學習門檻,讓所有人能以非常直觀,互動的方式近距離理解她。所以希望這個項目能給大家帶來方便吧。
TiDB Hackathon 2018 共評選出六個優秀項目,本系列文章將由這六個項目成員主筆,分享他們的參賽經驗和成果。我們非常希望本屆 Hackathon 誕生的優秀項目能夠在社區中延續下去,感興趣的小伙伴們可以加入進來哦。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/17841.html
摘要:拿到返回結果進一步的進行計算處理。比較痛苦的經歷不支持,我們就只好寫內置函數,就把另外一個模塊拖下來,自己修改加上語法,然后在加上自己設計的內置函數。其次就是涉及的的源碼模塊很多,從優化器執行器內置函數以及各種各樣的結構。 本文作者是來自 CC 組的蘭海同學,他們的項目《讓 TiDB 訪問多種數據源》在本屆 TiDB Hackathon 2018 中獲得了二等獎。該項目可以讓 TiDB...
摘要:拿到返回結果進一步的進行計算處理。比較痛苦的經歷不支持,我們就只好寫內置函數,就把另外一個模塊拖下來,自己修改加上語法,然后在加上自己設計的內置函數。其次就是涉及的的源碼模塊很多,從優化器執行器內置函數以及各種各樣的結構。 本文作者是來自 CC 組的蘭海同學,他們的項目《讓 TiDB 訪問多種數據源》在本屆 TiDB Hackathon 2018 中獲得了二等獎。該項目可以讓 TiDB...
閱讀 3125·2021-11-15 18:14
閱讀 1779·2021-09-22 10:51
閱讀 3290·2021-09-09 09:34
閱讀 3508·2021-09-06 15:02
閱讀 1024·2021-09-01 11:40
閱讀 3193·2019-08-30 13:58
閱讀 2528·2019-08-30 11:04
閱讀 1085·2019-08-28 18:31