五分鐘技術趣談 | 時序數據庫TDengine在和家親上的應用實踐

Part 01
業務背景
和家親APP作為中國移動智慧家庭業務入口,承載了大量智能設備告警推送和家庭業務推送。到目前為止,平臺每天產生將近30億的推送量,如何將這些推送數據進行存儲、查詢和分析是一個比較棘手的問題。最初我們使用的是mysql集群分庫分表方案,但隨著數據量的增加,遇到了數據寫入和查詢的瓶頸,而且運維復雜且不便管理。結合業務特點,同時也是響應集團去IOE的要求,我們開始調研新的存儲方案--國產開源時序數據庫(Time Series Database)。

圖1 和家親業務數據存儲方案演進
目前國產時序數據庫中比較有影響力的就IoTDB和TDengine,經過我們多維度的選型測試,最終確定選擇TDengine作為新的數據存儲引擎,我們發現業務數據某些特點非常契合TDengine:
- 高頻寫入,峰值寫入高達7W條/秒
- 數據很少更新且查詢簡單低頻
- 數據存儲周期自動調整
- 數據帶有時間戳
Part 02
數據建模
區別于傳統關系型數據庫,數據寫入之前需要提前建表,TDengine有超級表的概念,具備自動建表的功能。這樣業務數據入庫只需要建一個庫和一張與業務需求相關的超級表,就可以在數據第一次入庫的時候自動創建子表。自動創建子表在第一次入庫時會有性能折損,但是經過測試TDengine的自動建表效率非常高,幾乎可以忽略不計。在我們的業務場景中,我們把每個用戶對應成一個設備一張表,用戶每天產生的告警寫入到自己的表中。
建庫語句如下:
CREATE DATABASE `hjq_push` BUFFER 900 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 180m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 10 STT_TRIGGER 16 KEEP 10080m,10080m,10080m PAGES 160 PAGESIZE 128 PRECISION 'ms' REPLICA 3 WAL_LEVEL 1 VGROUPS 200 SINGLE_STABLE 0;超級表語句如下:
CREATE STABLE s_push (ts TIMESTAMP, guid BIGINT, source NCHAR(30),msgName NCHAR(64), msgContent NCHAR(1024), status SMALLINT, updateTime TIMESTAMP) TAGS(flag TINYINT);利用超級表寫入語句:
INSERT INTO u_#{phone} USING s_push TAGS #{tag} (ts, guid, source, msgName, msgContent, status,updateTime) VALUES(#{ts},#{guid}, #{source}, #{msgName}, #{msgContent}, #{status},#{updateTime});Part 03
性能表現
3.1 高效寫入
采用時序數據庫的一個重要原因就是支持高頻寫入。TDengine寫入速度極高,寫接近硬盤的連續寫入性能。經過業務實際測試,峰值寫入7W/s完全沒有壓力。

圖2 業務實測寫入
當然要達到高效的寫入性能,需要客戶端、數據源和服務端配合調試才能達到最優狀態。
從客戶端角度:
- 盡量在一條寫入sql中拼接更多數據。
- 寫入方式:參數綁定>sql寫入(不自動建表)>sql寫入(自動建表)>無模式寫入。
從數據源角度:
- 通過隊列(kafka)方式來提升數據并發寫入。
- 盡量將同一張子表的數據提前匯聚到一起,提高寫入時數據的相鄰性。
從服務器配置角度:
需要根據系統磁盤的數量、I/O 能力及處理器性能在創建數據庫時設置適當的vgroups數量以充分發揮系統性能。如果vgroups過少,則系統性能無法發揮;如果vgroups過多,會造成無謂的資源競爭。常規推薦vgroups數量為CPU核數的2倍,但仍然要結合具體的系統資源配置進行調優。
3.2 系統及存儲性能
TDengine已經在我們線上業務平穩運行一段時間,通過系統監控CPU使用率平常不到15%,內存使用率穩定在10%。另外由于其高效的壓縮算法,可以節省大量存儲空間,相比于之前MySQL集群存儲只有1/7。下圖為集群中一臺DNode機器的監控數據:
圖片
3.3 查詢性能
TDengine對常見ORM框架和數據庫連接池的支持較好,采用SQL作為查詢語言,開發簡單方便,對于之前使用關系型數據庫的開發者可以無縫切換。經過業務測試,在單個子表查詢都能達到ms級別。

圖3 業務查詢測試
Part 04
遇到的一些問題
在使用TDengine的業務實踐中,也遇到一些問題(可能有些問題在最新的版本更新迭代):
- 空子表無法自動清理,由于我們數據存儲有周期性,但目前的TTL策略只是針對數據而不是子表本身,針對空的子表淘汰還需要腳本介入。
- 缺少簡潔易操作的可視化界面。
- 數據更新會影響count()函數性能(商業版有碎片整理功能,沒試過)
- LAST_ROW函數返回的數據集字段帶有last_row(row),需要單獨解析
Part 05
結語
和家親推送業務對時序數據庫的使用目前也只是小試牛刀,相信隨著業務的發展,會使用到更多時序數據庫的功能特點。當然同樣的業務數據可能還存在更優的存儲方案, 無論是MySQL還是TDengine,都是優秀的數據庫產品,最終還是業務場景為王,只有適配業務數據才是好產品。




































