小 T 導讀:和(he)利時(shi)始(shi)創于 1993 年,業(ye)務集中(zhong)在工(gong)(gong)業(ye)自(zi)動化(hua)(hua)、交通自(zi)動化(hua)(hua)和(he)醫療大(da)健康三(san)大(da)領(ling)域,結(jie)合自(zi)動化(hua)(hua)與信(xin)息(xi)化(hua)(hua)兩方(fang)面的(de)(de)技(ji)(ji)術(shu)優勢,提出了(le)“智(zhi)能(neng)控制、智(zhi)慧管理、自(zi)主(zhu)可控、安(an)全(quan)可信(xin)”的(de)(de)戰略(lve)指(zhi)導方(fang)針。圍繞集團三(san)大(da)業(ye)務,公司對工(gong)(gong)業(ye)互(hu)聯網、大(da)數(shu)據、5G、信(xin)息(xi)安(an)全(quan)等新興技(ji)(ji)術(shu)開展更深入的(de)(de)研(yan)究和(he)應用(yong)(yong)示范(fan),打造(zao)面向各(ge)領(ling)域應用(yong)(yong)的(de)(de)工(gong)(gong)業(ye)互(hu)聯網平臺,進一步促進智(zhi)能(neng)制造(zao)解決方(fang)案(an)的(de)(de)落地(di)應用(yong)(yong)。
在物聯網場景下,面對龐大的時序數據處理需求,Oracle、PostgreSQL 等傳統關系型數據庫越來越吃力。基于此,目前國內外主流工業互聯網平臺幾乎都已經采用時序數據庫(Time Series Database),來承接海量涌(yong)入的工業數(shu)據。
究其原因,可以從數據的三個核心需求來解釋。我們都知道,企業在選擇數據庫、文件系統等產品時,最終目的都是為了以最佳性價比來滿足數據的三個核心需求:數據寫入、數據讀取、數據存儲。時序(xu)數據(ju)(ju)庫(ku)完(wan)全是按照(zhao)時序(xu)數據(ju)(ju)的(de)三個(ge)需求特征進(jin)行設計和(he)開發的(de),在數據(ju)(ju)處理上更加具(ju)有針對性:
- 在數據寫入上,如果將時間看作一個主坐標軸,時序數據通常是按照時間順序抵達,抵達的數據幾乎總是作為新條目被記錄,在數據處理操作上 95%-99% 都是寫入操作;
- 在數據讀取上,隨機位置的單個測量讀取、刪除操作幾乎沒有,讀取和刪除都是批量的,從某時間點開始的一段時間內讀取的數據可能非常巨大;
- 在數據存儲上,時序數據結構簡單,價值隨時間推移迅速降低,通常都是通過壓縮、移動、刪除等手段來降低存儲成本。
而(er)關系型數(shu)據庫主要應對(dui)的數(shu)據特點卻(que)大相徑(jing)庭:
- 數據寫入:大多數操作都是 DML 操作,插入、更新、刪除等
- 數據讀取:讀取邏輯一般都比較復雜
- 數據存儲:很少壓縮,一般也不設置數據生命周期管理
因此,從數據本質的角度而言,時序數據庫(不變性、唯一性以及可排序性)和關系型數據庫的服務需求完全不同。這也是我們一開始就鎖定時序數據庫來滿足工業互聯網場景的核心原因。
一、時序數據庫選型
我們對包括 InfluxDB、OpenTSDB、HolliTSDB(和利時自研時序數據庫)和 TDengine 在內的四款時序數據庫進行了選型調研及相關測試。測試數據的頻率為1秒鐘,數據集包含 10000 臺設備,每臺設備有 10000 條記錄,每條數據采集記錄包含 3 個標簽字段、2 個數據字段、1 個時間戳字段。測試對比項包括占用磁盤空間、百萬條數據遍歷查詢、聚合查詢(COUNT、AVG、SUM、MAX、MIN)。測試結果如下所示:
- 占用磁盤空間

- 百萬條數據遍歷查詢

- 聚合查詢COUNT

- 聚合查詢AVG

- 聚合查詢SUM

- 聚合查詢MAX

- 聚合查詢MIN

同等條件(jian)下(xia),TDengine 的壓縮率(lv)最(zui)(zui)高,數據占用的存儲(chu)空間最(zui)(zui)小;在原(yuan)始(shi)數據查詢(xun)上,OpenTSDB 最(zui)(zui)慢(man),TDengine 與 HolliTSDB 在伯仲之間;在聚合(he)查詢(xun)操作上,TDengine 最(zui)(zui)快,HolliTSDB 的速(su)度和 InfluxDB 相(xiang)當,OpenTSDB 最(zui)(zui)慢(man)。同時(shi),InfluxDB 只能單機(ji)部(bu)署,集群(qun)版本并未開源,且查詢(xun)性(xing)能存在瓶頸,其(qi) QPS 約為 30-50。
從性能測(ce)試結果來(lai)看(kan),我們選擇 TDengine Database 的原因(yin)主要源于以下幾點:
- TDengine 在查詢性能維度上的表現非常優異,滿足了我們的業務查詢需求
- 集群功能開源,方便橫向擴展,更彈性
- 在開源熱潮之下,支持如 TDengine 一般的國產開源數據庫、操作系統、中間件等也是企業的必修課
最終我們(men)決定(ding)接入 TDengine,以享(xiang)受(shou)更多(duo)元的本地(di)化支持和響應。
二、技術架構與實現
目前 TDengine 作為邊(bian)緣版時(shi)序數(shu)據庫在搭建使用,具體(ti)的技術架(jia)構如下圖所示:

基于 TDengine 進行建庫建表思路如下:
CREATE STABLE IF NOT EXISTS ts_super
(time TIMESTAMP, s BIGINT, vl BIGINT,vf DOUBLE,vb BOOL,vs BINARY(16349))
TAGS
(innerId BIGINT, namespace BINARY(256), id BINARY(256), type BINARY(1), seq int);
在構建列(lie)(lie)時(shi)(shi),包含(han)元素為(wei)time(時(shi)(shi)間,主鍵(jian))、s(數(shu)(shu)(shu)據(ju)(ju)(ju)質量)、vl(整(zheng)形類型數(shu)(shu)(shu)據(ju)(ju)(ju)L)、vf(浮(fu)點(dian)型數(shu)(shu)(shu)據(ju)(ju)(ju)F)、vb(布爾型數(shu)(shu)(shu)據(ju)(ju)(ju)B)、vs(字符(fu)串數(shu)(shu)(shu)據(ju)(ju)(ju)S),其中time、s是必填的列(lie)(lie),剩余列(lie)(lie)則要(yao)(yao)根據(ju)(ju)(ju)測點(dian)類型填寫,比如測點(dian)上(shang)報(bao)的是整(zheng)形數(shu)(shu)(shu)據(ju)(ju)(ju),就只需要(yao)(yao)設置time、s、vl這三(san)列(lie)(lie),vf、vb、vs這三(san)列(lie)(lie)為(wei)null。
在(zai)構建tag時,要包(bao)括innerId(測(ce)點內(nei)部編碼)、id(測(ce)點id)、type(測(ce)點類型(xing),L/F/B/S)、seq (序號(hao),L/F/B類型(xing)數據設置為0,S類型(xing)測(ce)點的seq可能為0,1,2,3…)
同時,在(zai)建(jian)庫(ku)建(jian)表的操作中我們也碰(peng)到了(le)一些(xie)小問題,放在(zai)這里給大家(jia)做(zuo)下(xia)參(can)考(kao):
- 因為表名不支持特殊字符,所以需要再生成一個唯一編碼作為表名;
- 查詢語句會被填充,導致查詢過程性能變慢,網卡被打滿。這種情況下只需要將查詢請求手動壓縮,就能有效降低帶寬占用率;
- TDengine 字符串最長可以有16374字節 ,超過的話需要從邏輯上處理。我們采用的方案是如果長度超過16374 ,截取該字符串,同一個測點再建新的表,通過tag關聯。
三、實際效果展示
數據庫配置
TDengine 集群5個節點(dian),副本數設置為3。修改配置為:
- minTablesPerVnode 10
- tableIncStepPerVnode 10
- compressMsgSize 1024
- rpcForceTcp 1
- httpMaxThreads 16
各(ge)節點(dian)機(ji)器配置如下:
| 節點名稱 | 節點IP | CPU核數 | 內存(G) |
| node1 | 20.5.2.53 | 8 | 16 |
| node2 | 20.5.2.54 | 8 | 16 |
| node3 | 20.5.2.55 | 8 | 16 |
| node4 | 20.5.2.49 | 12 | 16 |
| node5 | 20.5.2.50 | 12 | 16 |
查詢客戶端配置
客戶端(duan)共有三臺(tai)主(zhu)機(ji),每臺(tai)主(zhu)機(ji)上分別運(yun)行(xing)時序查詢及(ji)其對(dui)(dui)應(ying)的(de)AB,各主(zhu)機(ji)上的(de)時序查詢獨立運(yun)行(xing),分別啟動一/二(er)/三個時序查詢及(ji)其對(dui)(dui)應(ying)的(de)AB進行(xing)性能測(ce)試。
| 節點名稱 | 節點IP | CPU核數 | 內存(G) |
| query1 | 20.5.2.60 | 16 | 8 |
| query2 | 20.5.2.66 | 16 | 16 |
| query3 | 20.5.2.69 | 16 | 16 |
數據說明
共(gong)1000個測點(dian),80000萬條數據,數據頻率(lv)為每秒鐘(zhong)1條。存儲(chu)分布(bu)如(ru)下所示,存儲(chu)壓縮率(lv)不超過(guo)1/10。
| node1 | node2 | node3 | node4 | node5 | |
| 角色 | any | any | any | any | vnode |
| 數據量(vnode) | 376M | 1.4G | 1.4G | 1.9G | 919M |
查詢結果
| 時序查詢服務個數 | AB個數 | 每個AB并發 | 總QPS | 平均響應時長(ms) |
| 1 | 1 | 200 | 276 | 725 |
| 2 | 2 | 200 | 401 | 997 |
在我們的(de)(de)業(ye)務查(cha)詢當中,增(zeng)加QPS的(de)(de)主(zhu)要(yao)方式是(shi)增(zeng)加查(cha)詢的(de)(de)并發數。AB從1到2,QPS增(zeng)加了(le)45%,平均(jun)響應時間不超過1000ms,很好滿足了(le)客戶需求(qiu)
資源消耗(統計3個查詢服務的實例)
- TDengine node節點資源消耗

在(zai)(zai)(zai)查詢過(guo)程中,數(shu)據是相對均(jun)勻(yun)的(de)分布(bu),但是不同(tong)節點的(de)CPU消耗(hao)仍然有較大的(de)方差(cha)。這(zhe)是由于TDengine 的(de) RESTful 的(de)底層是在(zai)(zai)(zai)服務(wu)端通過(guo)單獨的(de)代(dai)理線程作(zuo)為客戶端查詢,所以會受到請求均(jun)勻(yun)度的(de)影響。如果 TDengine 在(zai)(zai)(zai)后續可以做代(dai)理層面的(de)負載(zai)均(jun)衡,相信能夠縮小這(zhe)個偏差(cha)。
查詢服務資源消耗

在查詢段的節點(dian)資源消耗還是(shi)相當大的,因為需要對(dui)查詢請求和結(jie)果(guo)進行(xing)處(chu)理。在具體(ti)業務中,可以考慮使用RPC接口(kou)來(lai)降低查詢服務的CPU消耗。
四、寫在最后
TDengine Database 在本(ben)項目中(zhong)展現出的性能(neng)(neng)效果非常顯著,推動本(ben)次項目快速且高質量落地(di),實現降本(ben)增效的目標(biao)。接下來,希望(wang) TDengine 能(neng)(neng)夠(gou)在以下兩個方(fang)向上(shang)有更大的進步,也祝(zhu)愿我們的合(he)作能(neng)(neng)夠(gou)越(yue)來越(yue)緊密:
- 希望可以通過觸發器或協處理器等方式,在服務端做數據過濾再返回,解決網絡壓力過大的問題
- 希望能夠進一步改善長度限制的問題


























