小 T 導讀:了解 TDengine Database 的朋友應該知道,TDengine 在處理時序數據時,有非常卓越的表現。這取決于我們對時序數據特點的挖掘和總結,并且 TDengine 充分利用時序數據的特點,設計了存儲模型和查詢模型。本文主要介紹 TDengine 的存儲引擎設計,看看 TDengine 是如何通過創新數據存儲引擎達到超強性能的。
一、時序數據的特點
我們先觀察一些時序數據,然后來總結一下時序數據的特點。

上圖展示了一些典型的時序數據,橫軸是時間,縱軸是采集量,可以看出:
- 有些時序數據在很長一段時間內都是固定的值,但是某些時間點也會產生異常跳變,異常檢測在時序數據的處理過程中,也是非常重要的一環,但本文不過多展開;
- 有些時序數據在一段時間內是一個變化趨勢;
- 有些時序數據在一定數值范圍內會進行波動,有些波動頻率高,有些波動頻率低;
- ……
因此我們總結出了時序數據的特點,如下圖所示,我們可以利用這些特點,進行存儲引擎的設計。

二、TDengine 的數據模型
TDengine Database 的數據模型主要有以下特點:
- 一個數據采集點一張表;
- 一張表的數據在文件中以塊的形式連續存放;
- 文件中的數據塊大小可配;
- 采用 Block Range INdex(BRIN)索引塊方法。
一個數據采集點一張表的設計邏輯會導致表的數量級膨脹,因此引入 vnode 的概念,對數據進行 Sharding。點擊《》可以詳細了解 vnode 的概念,這里不再過多闡述。
總的來講,vnode 是時序數據存儲的基本單元,一個 vnode 包含一定數量的表(數據采集點),數據的負載均衡、同步是以 vnode 為單位進行的,vnode 可以充分利用多核的特點,提高并發速度。
對于一個 vnode 內的數據,我們按照時間段對數據進行分區(Partition),將同一時間段的數據存儲在一個數據文件組中,并以文件組為單位對過期數據進行刪除。在我們的設計中,時間段和文件編號是一一對應的,因此,查詢某個時間段的數據,我們只需要計算出索引號,就可以到對應的文件中進行查詢。
三、 TSDB 存儲引擎
TDengine Database 針對時序數據的特點,專門研發了 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 碩士,本科畢業于中科大,是中科大郭沫若獎學金獲得者。主要研究方向為面向物聯網的大數據和機器學習技術。



























