項目背景
本項目為車聯網監控系統,系統由車載硬件設備、雲服務端構成。車載硬件設備會定時采集車輛的各種狀態信息,並通過移動網絡上傳到服務器端。
服務器端接收到硬件設備發送的數據首先需要將數據進行解析,校驗,隨后會將該消息轉發到國家汽車監測平台和地方汽車監測平台,最后將解析后的明文數據和原始報文數據存儲到系統中。
車輛的數據和其他數據需要通過web頁面或rest API接口進行查詢訪問。
要求半年內的數據查詢響應時間在毫秒級別內,超過半年的數據需要放到更加低成本的介質上,查詢延遲在3s以內,這些數據的查詢頻次比較低。
系統的主要參數有以下幾項:
- 10萬台車輛同時在線;
- 車輛正常情況下平均每分鍾發送兩個數據報文到監控平台;
- 若車輛處於報警狀態,則平均一秒鍾發送一次數據報文;
- 數據情況:(1)、車輛數據報文平均大小為1KB;(2)、解析后的數據包大小為7KB;(3)、平均一台車每天會產生20MB的數據;(4)、系統每天會產生2TB的數據;(5)同時系統有2.9億行的數據需要寫入到數據庫中;
- 系統並發量:(1)、3300的持續並發量;(2)、10萬個長連接;(3)、每秒3.3MB的原始數據需要被解析;(4)、每秒23.1MB的解析數據需要被存儲。
系統設計
系統的技術選型對初創公司來說至關重要,所以在設計系統的時候尤為小心。經過仔細分析,我們要求新系統必須滿足以下幾個條件:
- 必須能夠支持海量數據的不間斷寫入,而且能夠存儲PB級別的數據,具有高擴展性、高可靠性等;
- 能夠支持簡單的關鍵字查詢,響應時間在秒級別內;
- 能夠兼容大數據生態產品(如Spark、Hive、Hadoop等),同時支持離線和准實時OLAP;
- 優先選擇有雄厚實力的商業公司支持的雲平台,最大限度減少運維成本。
為何選擇HBase以及阿里雲
因為車輛的監控數據非常大,傳統關系型數據庫(如Mysql、pg等)已經無法勝任存儲工作,所以我們需要選用一種分布式數據庫用於存儲車輛實時數據。
我們在市場上能夠找到分布式數據庫有MongoDB和 HBase。
- MongoDB:MongoDB是一種我們曾經使用使用過的數據庫,該數據庫是一種基於文檔的數據庫。
支持分片副本集擴展,但是由於MongoDB的分片集群維護成本過高,另外查詢性能嚴重依賴索引,擴容時分片的遷移速度過慢。所以在這一版本的監控系統中我們並未采用。 - HBase:HBase底層存儲基於HDFS的面向列數據庫,其核心思想來源於谷歌三大論文內的bigtable。在谷歌和開源界均擁有豐富的應用實踐經驗。
除此之外,HBase還有以下特點:(1)、支持PB級別的數據量;(2)、壓縮效率非常高;(3)、支持億級別的QPS;(4)、在國內外很多大型互聯網公司使用;(5)、HBase添加節點及擴容比較方便,無需DBA任何干預。
經過對這幾種數據庫的分析,我們最終選用HBase,其滿足我們前面提到的四個要求,而且還提供Phoenix插件用於SQL語句的查詢。
作為初創公司,我們的運維能力有限,我們需要業務的快速落地。所以自建機房以及運維團隊意味着前期較大的投入以及高昂的運維成本,所以我們決定使用雲方案。
經過比較國內的各大雲廠商,我們最終選用了阿里雲平台,因為阿里雲提供SaaS化的HBase服務,同時阿里雲HBase支持很全面的多模式,支持冷數據存放在OSS之中,節約成本;
支持備份恢復等特性,做到了真正的native cloud的數據庫服務。
另外,HBase 在阿里內部部署超過12000台機器,歷經7年天貓雙11的考驗,這些實際數據以及經驗增強了我們對阿里雲HBase的技術信心,同時滿足了我們的技術和業務需求。
層級系統架構
系統采用層級架構以方便后期擴展和維護,現在主要分為以下幾層:
- 接入層:主要負責管理車輛設備的長連接,認證接收車輛發送的數據,下放數據和指令等操作。
- 消息隊列層:主要負責緩存接入層收到的車輛實時數據。
- 實時數據處理與解析層:主要負責解析車輛上傳的實時數據,並將其存儲到數據庫中。另外還需要負責數據轉發、指令生成等工作。
- 應用層:主要負責處理各種業務邏輯、將解析后的數據進行分析整理提供給用戶使用。
系統架構預覽
最終新能源監控系統的系統架構設計如下
圖中最左端為監控的車輛,它會實時采集車輛的各項數據,並把采集到的數據通過移動互聯網發送到平台。
平台驗證完數據會將其寫入到Kafka消息隊列中。流式計算服務器從Kafka消息隊列中取出車輛的原始數據,並對車輛的數據進行解析、存儲、轉發等操作。
HBase集群負責存儲車輛實時數據,MySQL負責存儲組織關系數據。同時,我們還會將超過一定時間(比如半年前)的數據轉存到OSS存儲介質中,以便降低存儲成本。
Spark ML會對系統中的各項數據進行分析。終端用戶會從HBase中查詢一些數據。
HBase使用難點
Row key 設計
團隊在使用HBase之前一直使用MySQL關系型數據庫,在系統設計之初並沒有考慮HBase的特性,而是按照關系型數據庫的設計原則設計。
經過一段時間的了解后才知道HBase主要使用Row key進行數據查詢。Row key的設計至關重要。
目前系統中設計的Row key如下
- 設備ID + 時間戳:此種方式可以快速定位單台車輛。但是由於設備ID前綴為型號,一旦某批次的設備或車輛發送故障,則會造成HBase的某個Region寫入壓力過大。
- subString(MD5(設備ID),x) + 設備ID + 時間戳:此種方式可以將所有車輛打散到每個Region中,避免熱點數據和數據傾斜問題,式中的x一般取5左右。但對於某個型號的車輛查詢就只能夠每台車輛單獨進行查詢了。
復雜查詢問題
雖然通過Row key的設計可以解決部分數據查詢的需求,但是在面對復雜需求時難以通過Row key 直接索引到數據,若索引無法命中,則只能進行大范圍或全表掃描才能夠定位數據。
所以我們在使用HBase時盡量避免復雜的查詢需求。但業務方面仍然會有部分較為復雜的查詢需求。針對這些需求,我們主要使用兩種方式來建立二級索引。
- 手動在事務產生時將索引寫入到HBase表中:使用這種方式建立索引雖然可以不借用第三方插件,但是事務的原子性很難得到保障,業務代碼也會因為索引的變化而難以維護。
另外索引的管理也較為麻煩,后期的數據遷移很難能夠。 - 通過Phoenix構建索引:通過Phoenix構建索引可以避免事務原子性問題,另外也可以通過重建索引來進行數據遷移。
因為使用的SQL語句,開發人員更能夠利用之前關系型數據庫的設計經驗建立數據索引。
目前新能源監控系統中主要使用Phoenix實現二級索引,大大增加了數據的查詢使用場景。
雖然Phoenix能夠通過二級索引實現較為復雜的數據查詢,但對於更為復雜的查詢與分析需求就顯得捉襟見肘。所以我們選用了Spark等其他數據分析組件對數據進行離線分析,分析后對結果通過接口提供給用戶。
多語言連接問題
團隊使用Python語言構建系統,但HBase使用Java語言編寫,原生提供了Java API,並未對Python語言提供直接的API。
我們使用happybase連接HBase,因為它提供了更為Pythonic的接口服務。另外我們也是用QueryServer 作為Python組件和Phoenix連接的紐帶。
HBase冷數據存儲
系統中車輛數據分為熱數據和冷數據,熱數據需要HBase中實時可查,冷數據雖不需要實時可查,但卻需要一直保存在磁盤中。
阿里雲HBase支持將冷數據直接存儲在OSS中,而這些數據的轉存只需要簡單的設置表相關屬性,操作非常簡單。將冷數據存儲在OSS之中大大減少了數據的存儲成本。
總結
首先,本文介紹了新能源車輛監控系統的項目背景,隨后分析了本項目的項目難點,並介紹了我們團隊的各種解決方案。
針對項目需求,介紹了我們選擇HBase的原因,及在HBase數據庫使用過程中的經驗和痛點。
展望
未來,我們會在系統接入大量車輛后,使用golang重寫高性能組件以滿足后期的並發性能需求。由於項目初期考慮到開發時間的問題,並未采用服務拆分的方式進行開發,這限制了系統的可擴展性,
后期我們會根據實際業務需求,將系統切分成相對獨立的模塊,增強擴展性可維護性。
另外,車輛數據積累到一定程度后,我們可以利用這些數據進行大數據分析, 如車輛的故障診斷,車輛狀態預測等,這樣就可以在車輛出現問題前提前發出預警,為車主和保險公司避免更大的損失,降低運營成本。

