上圖為 Prometheus 的官方系統(tǒng)架構圖,而實現(xiàn) TiPrometheus ,用到了上圖中沒有體現(xiàn)到的一個 Prometheus 的功能:Remote Storage ,如其名所示,其主要功能是給 Prometheus 提供了遠程寫的能力,這個功能對于查詢是透明的,主要用于長存儲。而我們當時的 TiPrometheus 實現(xiàn)了基于 TiKV 以及 PD 實現(xiàn)的 Prometheus 的 Remote Storage 。

核心實現(xiàn)

Prometheus 記錄的數(shù)據(jù)結構分為兩部分 Label 及 Samples 。 Label 記錄了一些特征信息,Samples 包含了指標數(shù)據(jù)和 Timestamp 。

Label 和時間范圍結合,可以查詢到需要的 Value 。

為了查詢這些記錄,需要構建兩種索引 Label Index 和 Time Index ,并以特殊的 Key 存儲 Value 。

l Label Index

每對 Label 為會以 index:label:<name>#<latency> 為 key ,labelID 為 Value 存入。新的記錄會 “,” 分割追加到 Value 后面。這是一種搜索中常用的倒排索引。

l Time Index

每個 Sample 項會以 index:timeseries:<labelID>:<splitTime> 為 Key,Timestamp 為 Value ,SplitTime 為時間切片的起始點。追加的 Timestamp 同樣以”,”分割。

l Doc 存儲

我們將每一條 Samples 記錄以 timeseries:doc:<labelID>:<timestamp> 為 Key 存入 TiKV ,其中 LabelID 是 Label 全文的散列值。

下面做一個梳理:

寫入過程

1. 生成 labelID

2. 構建 time index,index:timeseries:<labelID>:<splitTime>”ts,ts”

3. 寫入時序數(shù)據(jù) timeseries:doc:<labelID>:<timestamp> “value”

4. 寫入時序數(shù)據(jù) timeseries:doc:<labelID>:<timestamp> “value”

查詢過程

1. 根據(jù)倒排索引查出 labelID 的集合,多對 Label 的查詢會對 labelID 集合求交集。

2. 根據(jù) labelID 和時間范圍內(nèi)的時間分片查詢包含的 Timestamp 。

3. 根據(jù) labelID 和 Timestamp 查出所需的 Value 。

Why TiPrometheus

該項目最初源于參加 PingCAP 組織的 Hackathon ,當時希望與參與者一起完成大家腦海里的想法,其實最重要的事情就是,做出來的東西并不是為了單純的 Demo ,而是要做一個在實際工作中應用于生產(chǎn)環(huán)境的實際能力,且能解決生產(chǎn)中的問題。

剛開始還有過各種奇思妙想,包括在 TiSpark 上做一套 ML ,Hadoop over TiKV 等,不過這些想法實現(xiàn)起來都有些過于硬核,對于只有兩天工作時間就需要完成的項目來說,可能性太??;或者說,如果希望實現(xiàn) Demo ,所需 Hack 的點過多。而 GEO 全文檢索在融云現(xiàn)有的生產(chǎn)上,以及現(xiàn)有的系統(tǒng)中,也并沒有需要去填補的大坑,因此,也就沒有什么必要去在這方面花費力氣去解決一個并不存在的問題。

由于 IM 服務是一種計算密集型的服務,且服務質量是融云的核心競爭力;而目前存儲資源呈現(xiàn)出零散分布的節(jié)點,且每個節(jié)點的存儲資源使用率并不高,為了最大化利用現(xiàn)有的閑置資源,融云最終設計并實現(xiàn)了這套 TiPrometheus 系統(tǒng)。

Result

打通了 TiKV 與 Prometheus ,為基于 K , V 存儲的時序數(shù)據(jù)庫設計提供了一個可行的思路。

為 Prometheus 的長存儲提供了一套實用的解決方案。

已經(jīng)在融云內(nèi)部生產(chǎn)環(huán)境中進行部署與試用,并將逐步替換現(xiàn)有方案。

分享到

xiesc

相關推薦