TiPrometheus:基於 TiDB 的 TSDB | TiDB Hackathon 2018 優秀項目分享

本文做者是菜哥和他的朋友們隊的於暢同窗,他們的項目 TiPrometheus 已經被 Prometheus adapter 合併。該項目分兩個小項目,分別解決了時序數據的存儲與計算問題。存儲主要兼容 Prometheus 語法和數據格式,實現了精確查詢、模糊查詢,徹底兼容現有語法。全部數據僅存在 TiKV 中。計算主要經過 TiKV 調用 Lua 實現,經過 Lua 動態擴展實現數據計算的功能。

項目簡介

既然你關注了 TiDB, 想必你必定是個關注 Infrastructure 的硬漢(妹)子。監控做爲 Infra 不可或缺的一環,其核心即是 TSDB(time series database) 。node

TSDB 是一種以時間爲主要索引的數據庫,主要用來存儲大量以時間爲序列的指標數據,數據結構也比較簡單,一般包括特徵信息,指標數據和 timestamp。常見的 TSDB 包括 InfluxDB, OpenTSDB, Prometheus。git

而 Prometheus 是一整套監控系統,時序數據庫是它的存儲部分,下面這張架構圖來自於 Prometheus 官方,簡單歸納了其架構和生態的組成。github

1.png

Prometheus 還支持一個圖上沒有體現的功能 Remote Storage,能夠進行遠程的讀寫,對查詢是透明的。這個功能主要是用來作長存儲。咱們的項目就是實現了一個基於 TiKV 的 TSDB 來作 Prometheus 的 Remote Storage。數據庫

核心實現

Prometheus 記錄的數據結構分爲兩部分 label, samples。label 記錄了一些特徵信息。samples 包含了指標數據和 timestamp。數據結構

"labels": [{
    "job":        "node",
    "instance":   "123.123.1.211:9090",
}]
"samples":[{
    "timestamp": 1473305798
    "value": 0.9
}]

label 和時間範圍結合,能夠查詢到須要的 value。架構

爲了查詢這些記錄,咱們須要構建兩種索引 label index 和 time index,並以特殊的 key 存儲 value。併發

label index

每對 label 爲會以 index:label:<name>#<latency> 爲key,labelID 爲 value 存入。新的記錄會追加到 value 後面。這是一種搜索中經常使用的倒排索引。分佈式

time index

每一個 sample 項會以 index:timeseries:<labelID>:<splitTime> 爲 key,timestamp 爲 value。splitTime爲時間切片的起始點。新的 timestamp 會追加到 value 後面。oop

doc 存儲

咱們將每一條 samples 記錄以 timeseries:doc:<labelID>:<timestamp> 爲 key 存入 TiKV,其中 labelID 是 label 全文的散列值。測試

下面作一個梳理

2.png

寫入過程

  1. 生成 labelID
  2. 構建 label index,index:label:<name>#<latency> "labelID,labelID"
  3. 構建 time index,index:timeseries:<labelID>:<splitTime> "ts,ts"
  4. 寫入時序數據,timeseries:doc:<labelID>:<timestamp> "value"

查詢過程

  1. 根據倒排索引查出 labelID 的集合,多對 label 的查詢會對 labelID 集合求交集。
  2. 根據 labelID 和時間範圍內的時間分片查詢包含的 timestamp。
  3. 根據 labelID 和 timestamp 查出所需的 value。
扯完這些沒用的咱們來聊些正經的。

咱們爲何要作這樣一個項目

在 2018 年下半年,PingCAP 組織的 Hackathon,當時做爲萌新即將參加比賽,想着必定要文體兩開花,弘揚開源文化。

萌生了四個想法:

  • TiKV TSDB
  • Machine Learning on TiSpark
  • 魔改 TiKV + Lua 作成 mapreduce
  • geo 全文檢索

核心想法

  1. 能作出來,符合參賽要求。
  2. 確實能解決生產問題而不是一個比賽項目。

摸了摸頭髮,以爲 ML on TiSpark 太硬核,根本作不完。

TiHaoop 也太硬核,也作不完。

geo 沒在廠裏的生產中遇到什麼問題。

最後展轉反側思考一番,拍腦殼決定雙線操做,作基於 TiKV 的 TSDB 和 TiKV + Lua,完成時序檢索功能的同時,增長更豐富的算子(比賽前兩天才想好作什麼)。

比勝過程

週五

原計劃,提早看看 rust,做爲 rust 萌新。

因而前一天和同事借了本 rust 書,準備一天速成 rust。

後來發現仍是看電視劇更管用。

Day1(週六)

週六參加比賽的時候,原覺得會有個很長的開場致辭,因此決定 10 點再去。

到了現場,發現你們已經開始擼代碼了???

總體過程還算順利,但其中也遇到了一些問題。

Prometheus 的依賴和 TiKV 的一些依賴不兼容,因而 fork 一份 Prometheus 依賴,野路子改兩行,兼容了。

下午 5 點的時候,時序基本實現了,但聯調發現有數據讀寫不一致的狀況。因菜哥的一個 bug 致使,而後開始了漫長的 debug,一共歷時 5 個小時(特別說明,咱們組叫菜哥和他的朋友們)。

晚 10 點,準備回家了,不許備再 debug 了,一個 bug 查了 5 個小時。做爲娛樂隊,熬夜寫代碼是不可能。

各回各家,各找各媽。

Day2(週日)

開始漫長的半天精通 Lua 虛擬機 + rust。

也遇到了一些問題,好比爲何 TiKV 編譯這麼慢???一天只有 24 次編譯機會???

下午 2 點,做爲第一個講的團隊,咱們及時生成了一個 PPT ,畢竟 PPT 工程師的基礎還在。

一週後的週一

以前寫的渣代碼,簡單寫了個 README。抱着嘗試的心態,給 Prometheus adapter 提了個 PR。

而後,竟然被合進去了!!!

一下午寫的代碼竟然被合進去了!!!

成果

  • 完全打通了 TiKV 和 Prometheus。
  • 爲 TiKV 的時序存儲和計算提供了一個思路(以前作過 TiDB 存儲時序數據)。
  • 爲 Prometheus 的長存儲提供了一個還算好用的方案(M3 其實還能夠,Thanos 是分片機制,不能算真正意義的分佈式存儲)。
  • 已在公司生產環境試用,須要通過大數據量的測試,若是沒問題計劃替代現有方案。

感悟

參加 Hackathon,和週末加兩天班沒有太大的區別。

最早開始來,只是想混個獎品,好比說書包。去年參加 DevCon 給的布袋用了一年,還沒壞,今年準備再領一個。

見到了不少年齡比咱們小,但技術又還不錯的小夥伴,好比蘭海他們組,udf 那個組。也見到了一些年齡稍長的參賽者。

他們的存在,讓咱們在充滿瑣事的平常工做中又有了繼續奮鬥的動力。

彷佛,當時選擇這個行業沒有錯,而不只僅是一份工做。

Just for fun。

感謝

感謝唐劉老師和申礫老師的指導。

感謝 PingCAP 舉辦了這場大型網友見面活動,收穫頗豐。

項目地址:https://github.com/bragfoo/TiPrometheus (代碼比較渣,思路供參考)

打個廣告:

由菜哥和他的朋友們翻譯的書:《Go 語言併發之道》已登錄京東、淘寶。

很是棒一本 Go 語言書籍,搜索便可購買。

參考資料:

相關文章
相關標籤/搜索