從時序數據的特點說起,揭祕 TDengine 高性能的存儲引擎
小 T 導讀:瞭解 TDengine 的朋友應該知道,TDengine 在處理時序數據時,有非常卓越的表現。這取決於我們對時序數據特點的挖掘和總結,並且 TDengine 充分利用時序數據的特點,設計了存儲模型和查詢模型。本文主要介紹 TDengine 的存儲引擎設計,看看 TDengine 是如何通過創新數據存儲引擎達到超強性能的。
作者|程洪澤
本文編輯|李夏昕
01 時序數據的特點
我們先觀察一些時序數據,然後來總結一下時序數據的特點。
上圖展示了一些典型的時序數據,橫軸是時間,縱軸是採集量,可以看出:
-
有些時序數據在很長一段時間內都是固定的值,但是某些時間點也會產生異常跳變,異常檢測在時序數據的處理過程中,也是非常重要的一環,但本文不過多展開;
-
有些時序數據在一段時間內是一個變化趨勢;
-
有些時序數據在一定數值範圍內會進行波動,有些波動頻率高,有些波動頻率低;
-
……
因此我們總結出了時序數據的特點,如下圖所示,我們可以利用這些特點,進行存儲引擎的設計。
02 TDengine 的數據模型
TDengine 的數據模型主要有以下特點:
-
一個數據採集點一張表;
-
一張表的數據在文件中以塊的形式連續存放;
-
文件中的數據塊大小可配;
-
採用 Block Range INdex(BRIN)索引塊方法。
一個數據採集點一張表的設計邏輯會導致表的數量級膨脹,因此引入 vnode 的概念,對數據進行 Sharding。點擊《萬字詳解 TDengine 2.0 整體架構設計思路》可以詳細瞭解 vnode 的概念,這裏不再過多闡述。
總的來講,vnode 是時序數據存儲的基本單元,一個 vnode 包含一定數量的表(數據採集點),數據的負載均衡、同步是以 vnode 爲單位進行的,vnode 可以充分利用多核的特點,提高併發速度。
對於一個 vnode 內的數據,我們按照時間段對數據進行分區(Partition),將同一時間段的數據存儲在一個數據文件組中,並以文件組爲單位對過期數據進行刪除。在我們的設計中,時間段和文件編號是一一對應的,因此,查詢某個時間段的數據,我們只需要計算出索引號,就可以到對應的文件中進行查詢。
03 TSDB 存儲引擎
TDengine 針對時序數據的特點,專門研發了 TSDB 存儲和查詢引擎。作爲一個查詢引擎,它提供了基本的查詢接口。我們這裏主要講解 TSDB 的存儲引擎。TSDB 存儲了一個 vnode 中表的 META 信息以及時序數據(採集信息),後者以行和列兩種結構存儲(TDengine 2.0 開始引入行存儲)。時序數據在內存中以 SkipList 方式進行索引的,在硬盤中是以 Block Range INdex(BRIN)方式進行索引的。
META 數據
TSDB 存儲了 vnode 表中的 META 數據。META 包括表 / 超級表的 SCHEMA、子表 TAG 值、TAG SCHEMA 和子表 / 超級表的從屬關係。META 數據的添加、更新以及刪除等操作先在內存中進行,最後序列化並寫入硬盤。
META 數據在 TSDB 中是全內存加載的,根據子表的第一個 TAG 值建立一個內存索引,因爲只對 TAG 的第一個值索引,所以速度最快。使用 vnode 的 Sharding 方式可以充分利用多個 vnode 資源進行表的過濾查詢操作。
META 數據的持久化存儲
META 數據寫入內存時會同時生成序列化記錄,以 append only 形式存儲到內存 buffer 中。內存數據達到一定量後觸發落盤操作,落盤時,更新的序列化 META 數據以 append only 形式寫入硬盤 META 文件,每張表的最新狀態、表的更新和刪除都會 append 到 META 文件中,序列化成一條記錄。
時序數據
TSDB 也負責存儲 vnode 中表的時序數據(採集數據),時序數據在寫入時首先會寫入到 TSDB 事先分配的內存緩衝區中,當內存緩衝區的數據積累到一定量後,觸發落盤,然後進行持久化存儲。
TSDB 內存中的時序數據爲行存儲,因而支持以 append only 形式添加 buffer,從而充分利用已分配的內存資源,緩存足夠多的數據進行落盤,有利於一個塊的數據量進行積累,有利於壓縮。爲了便於查詢和亂序數據的處理,內存中建立了一個 SkipList 作爲內存索引。內存中還維護了已經寫入數據的最新時間和最老時間等信息。
內存中一條數據的行存儲格式如下圖所示。
時序數據的持久化存儲
TSDB 內存中的數據積累到一定量時,會觸發落盤。在落盤時,時序數據由行存儲形式轉化爲列存儲形式,並維護 BRIN 索引,引入 LAST 文件和 SUB-BLOCK 機制處理文件碎片化。列存儲形式如下圖所示。
TSDB 工作流程
TSDB 啓動時會事先分配一個 BUFFER POOL 作爲寫入緩衝(默認 16 MB*6=96 MB),緩衝區塊大小和個數可配,區塊個數可修改。META 數據和時序數據從緩衝塊申請寫入空間,寫入引擎向 BUFFER POOL 申請緩衝區塊,寫滿的緩衝區塊佔總緩衝區塊的 1/3 時觸發落盤操作。落盤時,緩衝區塊中的數據寫入到 META 等文件中,落盤結束後緩衝區塊歸還給 BUFFER POOL,形成循環機制。查詢時,對 MEM,IMEM 以及數據文件中的數據進行合併查詢。如下圖所示。
TSDB 設計的優點
-
對於單表按照時間段的查詢效率很高
-
內存行存儲充分利用內存,緩存更多數據
-
文件中列存儲充分發揮壓縮算法優勢
-
避免 LSM 過多的文件合併
-
標籤數據與時序數據分離存儲
總結
本文主要講解了 TDengine 的存儲引擎,當然,決定 TDengine 高性能和節省 TDengine 存儲空間的原因還包括先進的壓縮算法以及查詢模型的設計等。關注我們,後續會繼續詳解 TDengine 達到如此高性能的原因。
作者簡介:程洪澤,濤思數據聯合創始人,TDengine 核心作者。美國密西根大學 EE 碩士,本科畢業於中科大,是中科大郭沫若獎學金獲得者。主要研究方向爲面向物聯網的大數據和機器學習技術。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/VAVhcJ1YF-0wnjnrksH5UA