解密 雲HBase時序引擎OpenTSDB 優化技術

逝者如斯夫,不捨晝夜。   —— 孔子

時間如流水,一去不復返。自古不乏對時間流逝的感慨,而現代已經有不少技術記錄流逝的過去。咱們能夠拍照,能夠錄像,固然還能夠用時序數據庫!數據庫

時序數據庫是專門存放隨着時間推移而不斷變化的數據。近些年,隨着IoT等概念的流行,時序數據庫成爲數據庫一個相對獨立的領域逐漸受到重視,普遍應用於物聯網、監控系統、金融、醫療和零售等多種場景。併發

過去12個月時序數據庫(Time Series DBMS)熱度不斷增加

那麼雲上的用戶如何構建一個存儲海量數據的時序數據庫呢?筆者這裏推薦使用 雲HBase + OpenTSDB 方案。雲HBase是使用阿里多年優化過的HBase內核版本,本文不做過多介紹,詳情請看產品主頁測試

OpenTSDB簡介

OpenTSDB是一款基於HBase構建的時序數據庫,它的數據存儲徹底交給HBase,自己沒有任何數據存儲。全部節點是對等的,因此部署起來實際上是很是方便的。由於基於HBase,因此自己就具有了橫向擴展,存儲海量數據的能力。常見的部署模式有2種,一種分離部署,一種混合部署。優化

獨立部署,即與多個業務共享一個HBase。適合時序業務較小,或者用不滿HBase資源。ui

混合部署,即TSDB進程和RS在一個VM內。適合時序業務較重,須要獨享HBase。spa

上述2種模式,雲HBase產品都能提供支持,雲HBase購買頁面現已增長時序引擎購買入口。設計

OpenTSDB數據定義

一條時間線由 Metirc + 多個tag 惟一肯定,時間線上會有源源不斷的數據點(Data Point)寫入,數據點由時間戳和值組成。OpenTSDB支持秒級(10位整數),毫秒級別(13位整數)兩種時間精度。3d

舉個例子,好比咱們監控一個手環收集的心跳信息,那麼咱們能夠這樣定義:code

Metric: "band.heartbeat"
Tags: "id"               # 只定義一個tag,就是手環的ID

那麼咱們經過 band.heartbeat  + id=1  就能查詢到編爲1的手環收集到的心跳信息。blog

OpenTSDB數據存儲格式

數據表總體設計

這個設計有幾個特色:

  • 1.metric和tag映射成UID,不存儲實際字符串,以節約空間。
  • 2.每條時間線每小時的數據點歸在一行,每列是一個數據點,這樣每列只須要記錄與這行起始時間偏移,以節省空間。
  • 3.每列就是一個KeyValue,若是是毫秒精度,一行最多能夠有3600000個KV,這裏其實會有些問題,後面會講到。

RowKey格式

salt:打散同一metric不一樣時間線的熱點
metric, tagK, tagV:實際存儲的是字符串對應的UID(在tsdb-uid表中)
timestamp:每小時數據存在一行,記錄的是每小時整點秒級時間戳

metric和tag

它們長度默認是3個字節,即最多隻能分配 2^24=16777216 個UID。能夠經過這些參數調整:

tsd.storage.uid.width.metric # metric UID長度,默認3
tsd.storage.uid.width.tagk   # tagK UID長度,默認3
tsd.storage.uid.width.tagv   # tagV UID長度 默認3
# 這3者的UID分配分別是獨立的空間

注意:
集羣已經寫過數據後就沒法修改,因此最好是一開始就肯定好,建議4個字節。由於使用壓縮技術後,RowKey多佔的幾個字節能夠忽略,下文會提到。

salt

salt這個東西最好根據本身HBase集羣規模去配置,它有2個配置:

tsd.storage.salt.width   # 默認1,1基本夠了,不用調整
tsd.storage.salt.buckets # 打散到幾個bucket去,默認20

查詢的時候會併發 tsd.storage.salt.buckets   個Scanner到HBase上,因此若是這個配置太大,對查詢影響比較大,容易打爆HBase。這裏實際上是一個權衡,寫入熱點和查詢壓力。默認20其實我我的以爲有點多,配置3~8就差很少了,固然實際效果還和metric設計有關,若是在一個metric裏設計了不少時間線,那就得配置不少bucket。在一個metric中設計過多時間線,會影響OpenTSDB的查詢效率,因此不建議這麼作。
這個參數也是設置了就不能改的,因此也是要一開始規劃好。

Column格式

這是列名(HBase中稱爲qualifier)的格式,能夠看到毫米級須要多出2個字節。因此若是你的採集間隔不須要精確到毫秒級別,那請必定使用秒級(10位整數)。Value只能存儲整數和浮點,因此有一個bit存儲Float flag。

這裏你們必定會有疑問,直接經過qualifier長度是4仍是2不就能判斷是秒級精度的數據點,仍是毫秒了麼?爲什麼還須要MS flag這樣一個標記信息?閱讀下面的「壓縮」部分,就能知道爲何。

OpenTSDB壓縮問題

OpenTSDB有個很常見而且很麻煩的問題,就是整點時候對HBase對流量衝擊。下面2張圖是咱們一個測試集羣只作寫入對效果:

OpenTSDB

HBase

能夠看到會有一個數倍流量的爆發,要持續好久才能消化。這意味着咱們須要更高規格去抗這個峯值。首先咱們要明白OpenTSDB爲啥要作壓縮?在壓縮些什麼東西?

前面提到過OpenTSDB一行一小時的特色,那麼一行裏會有不少KV。表面上看起來好像沒什麼問題,可是實際上對比邏輯視圖和物理視圖你會發現一些問題。

很明顯,每一個KV都記錄了rowX,那rowX就是一個空間浪費。這個空間不只影響成本,還影響查詢效率(畢竟數據多了)。壓縮作的事情就是把多個小KV合成1個大KV,減小這部分浪費。因此壓縮的時候會涉及到對HBase的「讀-寫-刪」,這就是整點HBase IO流量的來源。

那麼咱們有沒有辦法,既作壓縮,同時又消除這部分HBase IO呢?

固然有!咱們能夠把壓縮的邏輯放到HBase內部去。由於HBase自己就須要對HFile作合併工做,這時候HBase自己就會讀寫數據文件,這部分對HDFS的IO不會少,而咱們經過hook在HBase讀出數據後,替換掉要寫入的數據(即壓縮好的數據)。

實現上面這個功能,固然須要必定內核開發量。好消息是經過雲HBase購買頁面購買的時序引擎,已經自帶了上述功能。不論是分離部署模式,仍是混合部署模式。

這個功能的好處顯而易見,消除峯值節省成本,提高集羣穩定性。這樣咱們對一個現有的HBase集羣空閒資源需求就不是那麼高了,徹底能夠複用了。下面是使用此功能後,一樣只作寫入的測試集羣的流量狀況:


本文做者:郭澤暉

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索