從時序數據的特點說起,揭祕 TDengine 高性能的存儲引擎

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

作者|程洪澤

本文編輯|李夏昕

01 時序數據的特點

我們先觀察一些時序數據,然後來總結一下時序數據的特點。

上圖展示了一些典型的時序數據,橫軸是時間,縱軸是採集量,可以看出:

  1. 有些時序數據在很長一段時間內都是固定的值,但是某些時間點也會產生異常跳變,異常檢測在時序數據的處理過程中,也是非常重要的一環,但本文不過多展開;

  2. 有些時序數據在一段時間內是一個變化趨勢;

  3. 有些時序數據在一定數值範圍內會進行波動,有些波動頻率高,有些波動頻率低;

  4. ……

因此我們總結出了時序數據的特點,如下圖所示,我們可以利用這些特點,進行存儲引擎的設計。

02 TDengine 的數據模型

TDengine 的數據模型主要有以下特點:

  1. 一個數據採集點一張表;

  2. 一張表的數據在文件中以塊的形式連續存放;

  3. 文件中的數據塊大小可配;

  4. 採用 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 設計的優點

  1. 對於單表按照時間段的查詢效率很高

  2. 內存行存儲充分利用內存,緩存更多數據

  3. 文件中列存儲充分發揮壓縮算法優勢

  4. 避免 LSM 過多的文件合併

  5. 標籤數據與時序數據分離存儲

總結

本文主要講解了 TDengine 的存儲引擎,當然,決定 TDengine 高性能和節省 TDengine 存儲空間的原因還包括先進的壓縮算法以及查詢模型的設計等。關注我們,後續會繼續詳解 TDengine 達到如此高性能的原因。

作者簡介:程洪澤,濤思數據聯合創始人,TDengine 核心作者。美國密西根大學 EE 碩士,本科畢業於中科大,是中科大郭沫若獎學金獲得者。主要研究方向爲面向物聯網的大數據和機器學習技術。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/VAVhcJ1YF-0wnjnrksH5UA