Opentsdb插入數據導致RegionServer寫入請求分佈不均勻

1. 配置文件

首先先普及一下Opentsdb的配置文件是怎麼獲取的,根據官方介紹,在輸入Opentsdb啓動命令如果你沒有指定 –config的路徑的話,會自動搜索以下路徑來尋找配置文件:
./opentsdb.conf
/etc/opentsdb.conf
/etc/opentsdb/opentsdb.conf
/opt/opentsdb/opentsdb.conf

2.Opentsdb在Hbase中是如何存儲的

個人感覺,如果想排查問題,必須要了解Opentsdb中的表結構是如何的,這裏就簡單的介紹下兩個表結構,tsdb和tsdb-uid:

圖一
圖一

1.\x00那一行是系統生成和維護的,value的值代表Metrics和tagk以及tagv的數量有多少個。
2.在Opentsdb中,Metrics ,tagk,tagv都會被映射爲一個三字節的唯一標識,我們稱爲uid,它們組合在一起就會形成一個序列的UID以及TSUID,在Opentsdb中每一個Metric,tagk,tagv都是從0開始計數,每當你要創造新的Metric,tagk,tagv,對應的uid就會加一,這裏是順序增長的,但是,這也會引入一個問題我們將在下面繼續討論

圖二
圖二

通過圖一和圖二兩個圖片我們可以看出tsdb存放的數據的映射是雙向的,我們既可以通過Metric,tagk,tagv找到它們對應的uid,也可以通過uid找到相對應的Metric,tagk,tagv。講到這裏,可能許多讀者對錶結構還是不夠清楚,所以這裏列出一個表格來更加方便大家直觀的看出‘tsdb-uid’的表結構:

圖三
圖三

表結構就如圖三所示因爲真實數據點位太長了,我就捏造了一些假的數據填入到表中,不過意思大同小異,我們可以看出,tagk和tagv單獨佔一行,這也是問什麼Opentsdb鼓勵我們複用tagk和tagv,因爲當我們建立不同的tagk和tagv越來越多時,Hbase中的行也就越多,那掃描‘tsdb-uid’的效率也會相應地降低。

接下來我們看一下實際存儲數據的tsdb表是如何設計的:

圖四
圖四

一個Hbase表設計的好不好,很大一部分看Rowkey設計的合不合理,同理,我們來看一下Opentsdb是如何在Hbase中設計表結構的。

rowkey的設計:
指標UID(指標+標籤的某個組合)+ 數據生成時間(取整點時間)+標籤1-Key的UID+標籤1-Vlaue的UID+…+標籤N-Key的UID+標籤N-Vlaue的UID

UID(Metrics name,3字節):\x00\x00\x01

數據生成時間(4字節):X\xED\xEC\x90 = 01011000 11101101 11101100 10010000 = 1491987600 相當於北京時間 2017/4/12 17:0:0 大家可能會有疑問,你這個時間,爲什麼剛剛好是整點,不能這麼巧吧,哈哈,當然不能這麼巧~不要忘記,Opentsdb是按照小時把數據聚合的,那具體到一個小時的某些時間,我們應該如何看呢?

我們看到列t後面有個值是\x0B\x1B將它轉化爲10進製爲2834,我們用1491987600+2834 = 1491990434 北京時間爲 2017/4/12 17:47:14 這樣我們不就能具體到某個小時內的某個時間點了呢,這樣做法的好處是大大減少了行數,節約了存儲空間,提升了檢索效率。

tagk(3個字節):\x00\x00\x01 對照我們上面的映射表,其實就是quality
tagv(3字節):\x00\x00\x01對照我們上面的映射表,其實就是我們的值192。
這倆組合在一起,不正好是quality = 192嘛?
接下來那個value其實就是這個點位的具體數值,16進制的,轉化的過程是一樣的,就不一一列舉了。

3遇到的問題

接下來就遇到了問題,先貼圖:

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述
圖5

偶然間我發現了Hbase的寫請求分佈的很不均勻,如上圖所示,大部分的寫請求集中在第一張圖片上,而且大部分的寫請求,集中在某個region上面,這樣會導致的問題是寫請求集中在某個RS上面,不能充分發揮集羣的特性,也就是寫操作時,只有其中幾臺RS發揮了功能,而其他的都在閒置狀態,並且你的寫操作,都集中在某些region上,這會導致region裏面的memstore很快就寫滿了,寫滿了之後就會flush操作,導致頻繁的flush操作,如果你頻繁寫入的region暫時不能發揮功能時,可能會導致Opentsdb寫入數據失敗等等一些問題。

4解決問題

我們現在的問題就是新寫入的數據都集中在某個RegionServer上的某個Region上面,首先想到的是Hbase中,如果數據都在一個Region上面,那麼它的rowkey一定是連續的,我馬上去看了下tsdb-uid表中的點位和uid的映射,發現瞭如下情況

這裏寫圖片描述
圖6

我們發現,我們剛插入的點位的uid都是連續的,還記得我們第二節提到的tsdb表中的Rowkey是以uids開頭的嘛,這也就是說,我們新寫入的數據都是遞增連續的,也就導致了我們新寫入的數據都集中在某個RegionServer上的某個Region上面,造成了寫入數據的熱點。

然後我查看了Opentsdb配置文件,tsd.core.auto_create_metrics,有一個這樣的點位,我們標識的是true,也就是自動生成uid和點位的映射,再加上文章開頭所說,uid的創建都是自增的,所以造成了熱點數據,那我想,有沒有可能使Rowkey前面的uid隨機一下呢,我去Opentsdb官網上配置信息頁面(http://opentsdb.net/docs/build/html/user_guide/configuration.html),看了一哈,確實找到了可以讓uids隨機生成一下的配置,tsd.core.uid.random_metrics (2.2),這個配置選項,只支持2.2以後的版本,2.1是不行的。。。。我把這個配置選項改成了True,問題得到了初步的緩解。

但是!!!!雖然問題得到了解決,我感覺還引入了其他的問題,我們隨機生成uids,uids的總共個數是2的24次方(3字節),也就是說隨機生成uid可能導致uid碰撞,然後導致寫入數據失敗!我看網上有人說,可以吧uid增長到8字節,減少碰撞概率,但是如果增長到8字節,Rowkey就會變得很長,官方其實也不是很推薦,所以,這個配置選項看個人或者我們可以採取預先創建uid來平衡分佈,但是我們具體也不可能完全知道有多少個點位,所以,問題是找到了,解決辦法也找到了,如何解決的話呢,還是要看具體的業務。希望大家結合自己的業務來選擇最合適的調優手段,而我最後拋出的問題,接下來我將會一一實踐,然後再下一篇文章中給出大家合理的解釋,如果大家遇到了我這種問題,不妨試一下tsd.core.uid.random_metrics (2.2)這個配置選項,前提是你的Opentsdb版本是2.2以後的哦~

因爲這篇文章是個人原創,可能還有許多不足或者錯誤的地方,希望廣大喜歡這方面的人多多提提建議,也可以加我的扣扣,具體的聯繫方式可以私信我,歡迎大家的批評和指正,麼麼噠~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章