1. 程式人生 > >通過例子剖析 OpenTSDB 的 Rowkey 及列名設計

通過例子剖析 OpenTSDB 的 Rowkey 及列名設計

通過例子剖析 OpenTSDB 的 Rowkey 及列名設計

 HBase  2018-11-16 14:37:21 466  3評論 下載為PDF 為什麼無法評論和登入

 

通過《OpenTSDB 底層 HBase 的 Rowkey 是如何設計的》 文章我們已經瞭解 OpenTSDB 底層的 HBase Rowkey 是如何設計的了。我們現在來測試一下 OpenTSDB 匯入的時序資料到底長什麼樣子。

在 OpenTSDB 裡面預設存時序資料的表為 tsdb

。前面說了,每個指標名稱、標籤名稱以及標籤值都有唯一的編碼,這些編碼資料是存放在 tsdb-uid 表裡面。為了更加深入的瞭解 OpenTSDB 的 Rowkey 設計,下面我們通過往 OpenTSDB 裡面插入一些測試資料,來加深理解。我們準備插入 OpenTSDB 的資料如下:

put sys.cpu.user 1541946115 42.5 host=iteblog cpu=0

put sys.cpu.user 1541946135 53.2 host=iteblog cpu=0

put sys.cpu.user 1542206107124 55 host=iteblog cpu=0

我們通過命令列往 OpenTSDB 插入上面的資料。執行完上面三個語句,我們來看下 tsdb 和 tsdb-uid 兩張表的資料長什麼樣子:

OpenTSDB Rowkey Design
如果想及時瞭解Spark、Hadoop或者Hbase相關的文章,歡迎關注微信公共帳號:iteblog_hadoop

從上面的輸出也可以看出,tsdb-uid 表就是儲存的是標籤名字、標籤值以及指標名字的編碼,以及編碼和標籤名字、標籤值、指標名字的關係。我們可以看到指標名字 sys.cpu.user、標籤名字 host 和標籤值 iteblog 的編碼均為 \x00\x00\x01;而標籤名字 cpu 和其對於的標籤值 0 編碼均為 \x00\x00\x02

。從這裡可以說明以下幾個問題:

  • 同一類資料的編碼只能唯一。比如指標名字的編碼必須唯一,不存在一個指標編碼對應多個指標名稱;
  • 不同類的資料編碼可以相同。比如前面 sys.cpu.user、標籤 host 和標籤值 iteblog 的編碼均為 \x00\x00\x01,因為它們之間是無影響的。

tsdb-uid 表中 Rowkey 為 \x00 的三行中的 id:metrics、id:tagk 以及 id:tagv 分別表示對應的指標名字、標籤名字、標籤值當前最大的編碼。

tsdb 表裡面有三行資料,這就是我們儲存的上面插入的資料的。我們可以看到第一行和第二行的 Rowkey 是一樣的,只是列名不一樣,這兩行對應的是上面 put 的前兩行資料。現在我們來分解這個 Rowkey:
\x00\x00\x01[\xE85\xE0\x00\x00\x01\x00\x00\x01\x00\x00\x02\x00\x00\x02
我們主要來分析時間戳,見上面加粗的部分。為什麼會顯示 [ 呢?其實這裡顯示的是 ASCII 對應的字元,所以這四個位元組([\xE85\xE0)對應的十六進位制是 5BE835E0,轉換成十進位制是 1541944800,這個正式我們前面分析的 2018-11-11 22:00:00 對應的時間戳。

 

接著我們來分析列名column=t:R; 這個其實也是 ASCII 對應的字元,十六進位制顯示為 523B,二進位制表示為 101001000111011。我們前面說過,其實列名裡面除了相對的秒數,其實還有當前列值得型別、值長度的資訊。

在 介紹如何解析列名之前,我們先來了解一些前提知識。在 OpenTSDB 裡面,如果 Rowkey 裡面的時間戳只到秒級別的,那麼列名稱佔用2個位元組。
其中後面三位代表當前列值佔用的位元組數。

 

  • 如果後三位為100,代表當前列值佔了8位元組;
  • 如果後三位為011,代表當前列值佔了4位元組;
  • 如果後三位為010,代表當前列值佔了2位元組;
  • 如果後三位為000,代表當前列值佔了1位元組;
  • 其他情況就是異常的。

倒數第四為代表當前列值的型別,

  • 如果為0,則代表整型資料;
  • 如果為1,則代表四位元組浮點型資料。

前面12位才表示相對於 Rowkey 的秒數。

如果 Rowkey 裡面的時間戳只到毫秒級別的,那麼列名稱佔用4個位元組。其中

  • 最前四位固定為全1;
  • 最後面四位的含義和前面一樣;
  • 倒數第5-6位為預留位;
  • 其他的位才是真正的相對於 Rowkey 裡面毫秒數。

所以列 column=t:R(二進位制 101001000111011)可以按照上面的規則進行解析:

  • 前12位二進位制為 10100100011,十進位制為 1315,這個就是我們前面分析的秒數!
  • 倒數第四位為1,也印證了我們的資料型別為浮點型。
  • 後三位為011,說明我們的資料值佔用了4位元組。

現在我們來解析 column=t:R 列對應的值。如上圖所示,這列對應的值為 B*\x00\x00,這個其實也是 ASCII 對應的字元,對應的浮點型十六進位制是 422A0000,由於其實一個浮點數,所以可以將這個十六進位制轉成十進位制,資料為 42.5,這就是我們 put 進去的資料啊。

現在我們來解析上圖中的第三行資料。我們可以看到,上面第三個 put 我們的時間戳精確到毫秒級別,所以我們需要按照上面的規則拆分 column=t:\xF8\x09\xBD\x00,我們可以將 \xF8\x09\xBD\x00 使用二進位制表示:11111000000010011011110100000000,我們對這個二進位制解析如下:

  • 這個二進位制的前4位均為1;
  • 倒數3位為 000,說明當前列對應的值佔用了一個位元組;
  • 倒數第4位為0,說明當前列對應值的型別為整型資料;
  • 除了前4位和後六位的二進位制,剩下的就是相對於 Rowkey 的毫秒數,剩下的二進位制為 1000000010011011110100,十進位制為 2107124。這個值正是 1542206107124 (2018-11-14 22:35:07)相對於 1542204000000(2018011014 22:00:00) 多出來的毫秒數。

現在我們來解析 column=t:\xF8\x09\xBD\x00 列對應的值。從上圖可以看出,這列的值為 7,其實這是 ASCII 字元,7對應的 ASCII 編碼十六進位制為 37,十進位制是 55,這不就是前面第三個 put 插入的值嘛。

正是因為 OpenTSDB 的這種 Rowkey 設計,才使得 OpenTSDB 能夠提供最高毫秒級精度的時間序列資料儲存,能夠長久儲存原始資料並且不失精度。它擁有很強的資料寫入能力,支援大併發的資料寫入,並且擁有可無限水平擴充套件的儲存容量。