一、項目背景
為(wei)了給用戶提供(gong)更好的(de)補能體驗,蔚來能源在(zai)加(jia)電(dian)基礎設施上進行了大量的(de)投入(ru),截止 2021 年(nian)底(di),已經在(zai)全國(guo)各地布局(ju)了換電(dian)站 777 座,超充(chong)樁 3,404 根,目充(chong)樁 3,461 根,為(wei)用戶安裝家充(chong)樁 96,000+ 根。
為了對設(she)備(bei)(bei)進(jin)行更高效的(de)管理,需要將(jiang)設(she)備(bei)(bei)采(cai)集數據上報至云端(duan)進(jin)行存儲,并提供實時數據查(cha)詢、歷(li)史數據查(cha)詢等業務服務,用(yong)來(lai)做(zuo)設(she)備(bei)(bei)監控和分析。
現狀
在業務誕生之(zhi)初,我(wo)們(men)用作數(shu)據存(cun)儲(chu)(chu)的選型是 MySQL + HBase,MySQL 存(cun)儲(chu)(chu)設(she)備最新實時數(shu)據,HBase 存(cun)儲(chu)(chu)設(she)備原始數(shu)據,大體架構(gou)如下:

之所以選(xuan)擇 HBase,有以下(xia)幾個理由:
- HBase 在大數據領域應用較為廣泛,適合存儲海量數據,寫入性能好
- 支持動態添加列,非常方便兼容數據模型變化
- 底層是鍵值對存儲,數據可以比較稀疏,空數據不占存儲空間
- 團隊 HBase 技術使用相對較為成熟
痛點
初期(qi)因(yin)為設(she)備不多,數(shu)據(ju)量不大,加上查詢場景單一,HBase 表現不錯,可(ke)以滿足(zu)業務需求。
隨著換電(dian)站和(he)超充站等(deng)設備(bei)在全國(guo)的(de)快速布局(ju),設備(bei)數量持續增長(chang),積(ji)累(lei)的(de)數據量越來越多,長(chang)時間跨度(du)數據查詢效率出現瓶頸,再加上查詢場(chang)景不斷豐富,HBase 已經無法滿足當前業務需要(yao)。問題主要(yao)體現在以(yi)下幾(ji)點:
- HBase 只支持 Rowkey 索引,有很大的局限性,一些查詢場景依賴 Rowkey 設計合理,如果業務調整,無法兼容
- 可以引入二級索引解決,單獨維護查詢條件與 Rowkey 關系,查詢時先查到 Rowkey 再查數據,不管是引入中間件還是自己實現,都會增加整體架構和實現復雜度
- HBase 單表隨著數據量增大,會觸發自動分區,導致寫入性能下降,需要通過建表時指定預分區來解決,調整起來很麻煩,需要重新建表生效
- HBase 不適用于大范圍掃描查詢,性能比較差
- HBase 不支持聚合查詢,大跨度時間范圍查詢數據量太大,圖表無法渲染
- HBase 部署需要依賴 ZooKeeper,運維成本高
二、落地方案
技術選型
為了解決這些痛點,我們將目光投向時下流行并且更適合物聯網領域的時序數據庫(Time-Series Database)。經過調研,對比多個技術選型,最終決定使(shi)用 TDengine 代替 HBase 作(zuo)為設備原始(shi)數據存儲。
在選型時我們考慮過 OpenTSDB,也是(shi)一(yi)款優(you)秀的時序數(shu)據(ju)庫產品,在部門其他業(ye)務中已經(jing)有過比較成(cheng)熟(shu)的使用(yong),能解決一(yi)部分遇到的痛點(dian):
- OpenTSDB 在 HBase 基礎上做了優化,包括存儲元數據映射和壓縮機制,使數據存儲占用空間大大降低
- OpenTSDB 提供數據聚合查詢功能,可以支持更大時間跨度查詢的業務需求
但(dan)是 OpenTSDB 底層還是基于(yu) HBase 的(de)(de),HBase 存在的(de)(de)一些問題,OpenTSDB 依然(ran)會有,并(bing)且架(jia)構(gou)并(bing)沒有變簡單,沒有擺脫 HBase 的(de)(de)依賴。
經過對比(bi),我們決定嘗試一(yi)下 TDengine Database,其(qi)官方給出的性能(neng)指(zhi)標,單(dan)節點部署情況下可以達到 14810 k/s 讀取,和 880k/s 寫(xie)入,同時 TDengine 具備的一(yi)些特(te)點能(neng)很(hen)好地解決我們遇(yu)到的痛點:
- 引入超級表概念對應設備類型,對每個設備創建子表繼承超級表,通常相同設備類型的設備數據模型一定相同,通過超級表管理 schema 直接對子表生效很方便,同時對每個設備建表可以很好地做數據隔離,同時避免互相影響
- 采用多級存儲,不同時間的數據使用不同存儲介質,新數據經常訪問存 SSD 保證效率,老數據存 HDD,節約成本
- 不依賴任何第三方軟件,集群安裝部署方便,支持靈活擴容
- 提供多種聚合函數,支持對數據的聚合查詢
前期測試
我(wo)們使(shi)用 TDengine 做了一(yi)些簡(jian)單的(de)性(xing)能(neng)測試,評估使(shi)用 TDengine 是否能(neng)滿足我(wo)們的(de)業(ye)務(wu)需(xu)求。
測試準備
- 采用單節點部署
- 8 核 32GB,500GB 存儲
- 采用默認配置
- 采用 RESTful API 方式寫入數據
測試場景
模(mo)擬 10,000 個設備上報數據,消息并發約 4k 左右。
- 定義超級表如下
SQL -- 代碼示例,非真實代碼
CREATE STABLE device_data_point_0 (ts timestamp, d1 nchar(64), d2 nchar(64), ...) TAGS (t1 binary(64));
- 最初采用每條上報消息進行一次數據寫入,性能無法滿足,而將單條消息寫入改為批量寫入,積累一批數據(100 條)后,再批量寫入一次,性能可以支撐


測試結論
采用批(pi)量(liang)(liang)寫(xie)(xie)(xie)入(ru)數據(ju)方式,調整合(he)適的單(dan)批(pi)次數據(ju)量(liang)(liang)大小(xiao),使用單(dan)機部(bu)署(shu)(8 核 32 GB,500 GB 存儲)默認配(pei)置的 TDengine 服務,RESTful API寫(xie)(xie)(xie)入(ru)方式,在 4k 并(bing)發流量(liang)(liang)下寫(xie)(xie)(xie)入(ru)沒(mei)有問題(ti),同(tong)時(shi)消費積(ji)壓數據(ju)時(shi)峰值達到 7 k/s,因為(wei)(wei)單(dan)條消息包含信息量(liang)(liang)太大,實(shi)際處(chu)理中(zhong)會拆分為(wei)(wei) 30 條寫(xie)(xie)(xie)入(ru) TDengine,所(suo)以實(shi)際寫(xie)(xie)(xie)入(ru) QPS 為(wei)(wei) 210 k/s,比滿足同(tong)樣(yang)數據(ju)流量(liang)(liang)的 HBase 集(ji)群規模要小(xiao)不少,可(ke)以節省成本(ben),再加(jia)上 TDengine 本(ben)身部(bu)署(shu)不依賴其他三方軟件,也可(ke)以同(tong)時(shi)節省運維成本(ben)。
遷移方案
經(jing)過測試,我們決定先(xian)對部分設備應(ying)用 TDengine 時(shi)序數據庫替代(dai) HBase,同(tong)時(shi)需要考慮如何在不(bu)影響業(ye)務功能(neng)的情況下平滑過渡并完成遷移。
數據雙寫
因為目前沒有現成的工具可以直(zhi)接把(ba)數據從(cong) HBase 遷移到 TDengine,如果自己開發(fa)一個(ge)工具做這(zhe)件事情,開發(fa)成本(ben)太高,而(er)且可能是一次性的。
考慮到不想浪(lang)費開發(fa)資源(yuan),同時我(wo)們需要(yao)一個(ge)過渡期,期間如果 TDengine 出現問題(ti)可以迅速切(qie)換回 HBase,不影響(xiang)業(ye)務,所(suo)以不能(neng)馬(ma)上把 HBase 廢掉,所(suo)以我(wo)們決(jue)定先實現 TDengine 寫入,并且暫(zan)時保持 HBase 和 TDengine 兩(liang)個(ge)數據庫(ku)雙寫。
寫入方式
根據(ju)(ju)前(qian)期測(ce)試結果,我們選擇直接采用批量方式(shi)寫入數(shu)據(ju)(ju):
- 并行處理不同設備類型數據
- 消費設備上報數據放入隊列
- 當隊列長度達到n或超過等待時間t,從隊列中取出數據批量寫入
經過壓測,在n = 1,000,t = 500 ms 情(qing)況(kuang)下,單次(ci)寫(xie)入(ru)耗時基(ji)本在 10 ms 以內,意味著我們可(ke)以支(zhi)持單個設備類型每秒上萬的(de)(de)并發寫(xie)入(ru),并且還有進一(yi)步(bu)的(de)(de)優化(hua)提升空間(jian)。
查詢切換
為了保證遷移(yi)過程順利,并(bing)且(qie)遷移(yi)前(qian)后不會出現數據(ju)不完(wan)整的(de)情況,我們做了一(yi)個查(cha)詢開關:
- 配置 TDengine 功能上線時間
- 判斷查詢請求時間范圍與配置時間大小,決定查 HBase 還是 TDengine
- 過渡期結束后,停止 HBase 服務
遷移后架構變為如下所示:

三、實際效果
目前我們(men)已將線(xian)上(shang)部分設(she)備(bei)的數據切換到 TDengine Database 集群(qun)(qun),上(shang)線(xian)后集群(qun)(qun)表現穩定。

對比之前(qian)使用(yong) HBase:
- 查詢速度提升明顯,從使用 HBase 查詢單設備 24 小時數據的秒級返回,到使用 TDengine 查詢查詢相同數據的毫秒級返回
- 每天增量數據占用的存儲空間相當于原來使用 HBase 時的 50%
- 集群計算資源成本相比使用 HBase 節省超過 60%
四、總結
- 總體上說,TDengine 讀寫性能表現很好,在滿足我們業務需求的同時,極大地節省了計算資源和運維成本,目前嘗試 TDengine 的業務場景還比較簡單,只是單純的數據寫入和時間范圍查詢,后續可以結合 TDengine 更多進階功能探索其他可以落地的業務場景
- 使用上還有一些問題待解決,比如 schema 調整在應用發版過程中對數據寫入的影響,產生預期外的寫入異常,以及異常定義不明確,無法快速定位問題,尤其是跟 schema 相關數據寫入問題
- 監控方面目前支持的監控指標較少,這個問題據說會在后續版本豐富
- 數據遷移方面,目前官方支持工具還比較少,不能比較方便的把數據從其他存儲引擎遷移到 TDengine,需要進行額外開發
關于作者
李鵬飛(fei),蔚來汽車(che)能源數字化產品開(kai)發部高級工程師,目前負責能源物聯平臺開(kai)發。


























