Prometheus 與 國產 TDengine 的對比
通過對比,能加深對這兩個系統的理解,方便後續架構選型時作出正確決定。他們的設計思路有很多值得借鑒的地方,雖然工作中需要用到這些知識的地方不多,但是了解他們的設計細節能極大滿足我的好奇心。
1.場景和需求
Prometheus
需求
- 用於雲原生場景下集群監控數據的收集、即席分析(Ad Hoc)和報警
- 處於 Kubernetes 生態,需要能很方便與之集成,被收集對象(target)的種類和數量會動態變化
- 可擴展:能應對集群規模逐步變大的場景:從成百到上千台機器,上萬容器的規模
- 追求單機模式下極高的寫入吞吐和查詢速度,比如支持每秒百萬採樣數據的寫入。
場景特點
- 因為生態中已經有服務發現組件,而且是內網環境,所以它會定期、批量拉取數據,需支持高並發寫入。
- 需要存儲的指標序列(metric series)數量級會很大。比如一個 Kuberntes 集群中500台機器,每台機器上有幾十上百個目標,每個目標里20個指標。這樣會有 500*100*20 = 1,000,000,一百萬個序列。
- 數據寫入和讀取的形式完全不同:數據寫入按照指標維度,而讀取是按照時間區間。最終查詢時涉及的區域以時間為橫軸,指標不同維度為縱軸的矩形。
- 序列翻騰(Series Churn)問題:隨着時間推移,一些指標序列會進入非活躍狀態,即再也不會接收到新的數據,而新的序列會出現。這在雲環境,尤其是 Kuberntes 這種環境下非常常見:主機粒度、服務實例粒度、容器粒度都會彈性伸縮。
TDengine
需求
- 想要一站式解決目前國內物聯網大數據平台的問題:使用互聯網的Kafka、HBase、Cassandra、MongoDB、Redis等太重了,研發、運維效率低,定位問題鏈條太長
- 希望輕鬆搞定私有化部署
- 能適用於物聯網中嵌入式設備和系統
場景特點
- 寫入的都是結構化數據,數據 Schema 是事先能確定的
- 寫多讀少,寫入數據都帶時間戳
- 寫數據流量平穩且可預期。根據設備數量和採集頻次,可以預測。比如有100個設備,每30s採集一次數據,那寫入最高約3000次每秒。不會像互聯網的To C 流量,會受營銷的影響。
- 嵌入式設備,存儲、算力資源受限,而且設備有利舊的情況
2. 需求共同點
他們的需求和場景有一些共同點:
- 寫入數據都帶時間戳,一次寫入,多次讀取,寫入的數據不會有更新的需求。
- 查詢都是基於連續的時間區間,聚合都是基於更小的時間窗口。比如查詢某指標在最近30分鐘里,5分鐘為窗口的平均值
- 需要提供即席查詢(Ad Hoc)能力,即支持用戶自定義查詢條件。不需要支持跨不同類型的表進行聚合查詢的情況。
3. 差異
面向的場景不同
- Prometheus 專註於運維(operation)需要的指標數據,特點是存儲的就是一個數值,數據附帶了很多維度信息,作為標籤(lable)。比如 cpu_total_seconds :
{timestamp=2020-09-05-21-27, host="192.168.1.10", type="idle"}=3551341
;而 TDengine 類似傳統數據庫,用於存儲工業中某類傳感器設備採集的指標,所以數據類型多樣,如浮點,字符串等。 - TDengine 面向工業物聯網時序場景,寫入數據的設備數量比較穩定,可預測。而 Prometheus 要拉取的目標是動態變化的。
- TDengine 的場景之一是嵌入式,所以追求無依賴,安裝包小,內存佔用小。
- TDengine 面向工業物聯網,這個領域不像互聯網那樣人才充沛,IT化程度低,所以 TDengine 想減少維護成本,做全棧,有一部分緩存(無需Redis)、消息隊列(無需Kafka)、實時計算能力
- Prometheus專註於單機性能,用於存儲最近一段時間數據,沒有長期持久化的考慮,弱化分佈式集群功能,由其他組件(如Thanos)來完成高可用。
- TDengine 希望通過分佈式集群來提供可擴展性、高可靠和高性能,避免單點故障,收費版就是提供集群能力,有持久化多級存儲在不同設備上的能力。
使用方式不同
- Prometheus 不需要提前建表,而 TDengine 是關係型數據庫模型,需要提前定義好表結構。Promtheus 里寫入的數據需要自帶描述,包含很多不同維度的標籤(lable),這些都是動態的。
- 查詢語句:TDengine 使用 SQL 語句。而 Prometheus 有自己的一套 DSL:PromQL
- TDengine 一個採集點一張表,所以一張表不會並發寫入。而 Promtheus 為了避免存儲的採樣數據產生很多小文件,是以塊為單位存儲指標的
- Prometheus 里 lable 會有字符串,所以查詢語句支持文本檢索:與、非條件組合
架構、實現方案不同之處
- TDengine中集群功能非常複雜,它需要考慮很多分佈式系統里常見的問題:集群成員管理(membership management)、成員通信、數據分片(sharding)、數據分區(partition)、成員選主(leader election)、數據同步(replication)、負載均衡(load balance),防止數據過熱或傾斜,
- 上文提到 Prometheus 沒有聚焦在解決分佈式高可用。它的核心組件是自研的時序數據庫 TSDB。通過學習Facebook的開源時序數據庫 Gorilla 中的採樣數據壓縮算法,號稱能把一個16位元組的採樣數據壓縮到約1.4位元組。
- TDengine 使用 C 來實現,為了避免對其他庫有依賴和較量高效,自己實現了定時器,RPC,內存管理等機制。
相同點
共同的設計目標
都在追求高性能、低資源佔用率,都希望充分利用數據的使用特點:最近寫入數據優先。
類似的架構、實現方案
- 寫入時,數據都是先寫入內存,之後批量刷到磁盤,盡量減少磁盤的寫頻率。為了防止在此期間的宕機,都使用了提前寫(Write-ahead-log)日誌
- 為了盡量減少數據的內存和磁盤佔用,都會根據數據特點進行壓縮。
- 數據都按照時間維度進行分塊(chunks),塊與塊之間獨立。這樣查詢時可以多個塊並發查詢,然後進行合併。而且後續數據回滾(retention),可以以塊為粒度進行,簡單高效。
- 如果查看他們的架構圖,會發現都需要有存儲引擎、計算引擎。
本文中還有很多方面沒有涉及,比如 TDengine 集群模式及存儲引擎方面的細節。由於 TDengine 存儲引擎無文檔,目前還不知道是如何設計的,改日讀讀源碼,後續逐步寫文章闡明。
通過學習這些系統,會發現技術領域也有經典招式,存在了很多年,威力巨大。比如 WAL,Master slave 同步機制, Raft協議、Quorum 機制,SSTable 等。
參考資料
- 我為何要開發一個專用的物聯網大數據平台,還開源它?
- PromCon 2017: Storing 16 Bytes at Scale
- Writing a Time Series Database from Scratch