HBase在移動廣告監測產品中的應用

TalkingData發表於2019-04-19

1、HBase在Ad Tracking的應用

1.1 輸入標Ad Tracking的業務場景題

Ad Tracking是TalkingData的移動廣告監測產品,其核心業務模型是歸因。App使用者點選廣告之後,及隨後安裝廣告跳轉到的應用或者遊戲,Ad Tracking會對這些點選事件(使用者點選廣告的行為)和啟用事件(使用者安裝應用的行為)進行監測。

歸因需要做的是,接收到啟用事件之後,通過啟用事件匹配之前接收到的點選事件,如果啟用歸因到了點選,那麼這個啟用事件就是點選廣告帶來的,也就歸因到了該廣告對應的推廣活動,而推廣活動對應某個渠道,歸因到了推廣活動就歸因到了投放廣告的渠道等。後續的所有效果點事件(例如應用內的註冊、登入等事件)也都將通過對應的啟用事件找到對應的推廣活動資訊。

啟用和各種效果點事件的原始資訊,包括對應的裝置、歸因到的推廣活動等,都可以提供給Ad Tracking使用者為參考——Ad Tracking的資料匯出功能。

1.2 HBase與資料匯出

HBase作為一個分散式的列式儲存,擁有強悍的資料寫入能力,由於是列式儲存,隨著後期需求的增加,可以動態的增加儲存的欄位,非常契合Ad Tracking的資料匯出的業務場景。

通過合理的設計rowkey,HBase又能保證很快的查詢速度,使用者在Ad Tracking後臺進行資料匯出之後,基本上秒級時間就能夠完成資料的下載,能夠保證很好的匯出體驗。

下面將對HBase的架構原理和Ad Tracking資料匯出功能中的應用進行介紹下。

2、HBase的架構

HBase在移動廣告監測產品中的應用

圖:HBase的基本架構

  • master:

    ▫表的操作,例如修改列族配置等

    ▫region的分配,merge,分割

  • zookeeper:

    ▫維護伺服器存活、是否可訪問的狀態

    ▫master的HA

    ▫記錄HBase的後設資料資訊的儲存位置

  • region server:資料的寫入與查詢

  • hdfs:資料的儲存,region不直接跟磁碟打交道,通過hdfs實現資料的落盤和讀取

3、資料的寫入

3.1 資料的寫入過程

HBase在移動廣告監測產品中的應用

圖:資料的寫入概覽

  • WAL:write ahead log,資料首先寫入log,保證資料不丟失,該log也是儲存在hdfs上

  • MemStore:資料進入記憶體,按照rowkey進行排序

  • HFile:MemStore中的資料到達一定量或者一定時間,建立HFile落盤

3.2、資料格式

HBase儲存的所有內容都是byte陣列,所以只要能轉化成byte陣列的資料都可以儲存在HBase中。

4、儲存模型

HBase在移動廣告監測產品中的應用

圖:HBase的儲存概念模型

  • 表:一個表由一個或者多個列族構成

  • 行:一個行包含多個列,列通過列族進行分類,每一行都有唯一主鍵rowkey

  • 列族:列族包含若干列,這些列在物理上儲存在一起,所以列族內的列一般是在查詢的時候需要一起讀取。資料的屬性,例如超時時間、壓縮演算法等,都需要在列族上定義

  • 列:一個行包含多個列,多個列維護在一個或者多個列族中

  • 單元格:列的內容儲存在單元格中,如果有過更新操作,會有多個版本

5、儲存實現

HBase在移動廣告監測產品中的應用

圖:HBase的儲存結構

5.1 region

Table的資料以region的形式分佈在所有的伺服器上。region的存在是為了解決橫向擴充套件問題。

5.1.1 region的拆分

通過將資料均衡的分佈到所有機器上,可以充分利用各個伺服器的能力,提高查詢速度。隨著資料的不斷寫入,region會不斷增大,region太大會影響查詢效能,所以hbase會自動對region進行拆分。

下面是兩種常見的region的拆分策略:

  • ConstantSizeRegionSplitPolicy:老版本的Hbase使用的拆分策略,按照固定的大小進行拆分,預設為10G。缺點:太死板、太簡單,無論是資料寫入量大還是小,都是通過這個固定的值來判斷

  • IncreasingToUpperBoundRegionSplitPolicy:新版本的預設策略,這個策略能夠隨著資料增長,動態改變拆分的閾值。

5.1.2 region的merge

場景:region中大量資料被刪除,不需要開始那麼多region,可以手動進行region的merge

5.2 store

一個region內部有多個store,store是列族級別的概念,一個表有三個列族,那麼在一臺伺服器上的region中會有三個store。

5.2.1 MemStore

每個列族/store對應一個獨立的MemStore,也就是一塊記憶體空間,資料寫入之後,列族的內容進入對應的MemStore,會按照rowkey進行排序,並建立類似於Btree的索引——LMS-Tree。

LMS-Tree(Log-Structured Merge Tree)

LMS樹採用的索引結構與B+Tree相同,而且通過批量儲存技術規避磁碟隨機寫入問題,因為資料過來之後,首先會在記憶體中進行排序,構建索引,當到達一定的量的時候,flush到磁碟中,隨著磁碟中的小檔案的增多,後臺進行會自動進行合併,過多的小檔案合併為一個大檔案,能夠有效加快查詢速度。

HBase在移動廣告監測產品中的應用

圖:LMS樹的合併

flush時機:

  • 大小達到刷寫閥值

  • 整個RegionServer的memstore總和達到閥值

  • Memstore達到刷寫時間間隔

  • WAL的數量大於maxLogs

  • 手動觸發flush

5.2.2 HFile

HBase的資料檔案,HBase的所有資料都儲存在HFile中,查詢的時候也是從HFile中進行查詢。

HFile包含多個資料塊,儲存了一個列族內的資料,以及相關的索引:

  • scan block:scan查詢的時候需要讀取的部分

    ▫data block:資料KV儲存

    ▫leaf index block:Btree的葉子節點

    ▫bloom block:布隆過濾器

  • none scan block

    ▫meta block

    ▫intermediate index block:Btree的中間節點

  • load on open:HFile載入的時候,需要載入到記憶體的部分

    ▫root index block:Btree的根節點

    ▫meta index

    ▫file info

    ▫bloom filter metadata:布隆過濾器的索引

  • trailer:記錄上面各個部分的偏移量,HFile讀取的時候首先讀取該部分,然後獲取其他部分所在的位置

Hfile的compaction:

每次memstore的刷寫都會產生一個新的HFile,而HFile畢竟是儲存在硬碟上的東西,凡是讀取儲存在硬碟上的東西都涉及一個操作:定址,如果是傳統硬碟那就是磁頭的移動定址,這是一個很慢的動作。當HFile一多,每次讀取資料的時候定址的動作變多,查詢速度也就變慢。所以為了防止定址的動作過多,需要適當地減少碎片檔案,後臺需要持續進行compaction操作。

compaction的分類:

  • 小compaction:小的HFile的合併成大的

  • 大compaction:大的最終合併成一個,注意:只有在大compaction之後,標記刪除的文件才會真正被刪除

compaction的過程:

  • 讀取compaction列表中的hfile

  • 建立資料讀取的scanner

  • 讀取hfile中的內容到一個臨時檔案中

  • 臨時檔案替換compaction之前的多個hfile

6、資料查詢

6.1 查詢順序

1. 首先查詢block cache:HFile的load on open部分是常駐記憶體的,data block是在磁碟上的,查詢的時候,定位到某個data block之後,HBase會將整個data block載入到block cache中,後續查詢的時候,先檢查是否存在block cache中,如果是,優先查詢block cache。之所以可以這麼放心的使用block cache,是基於Hfile的不可變性,後續的修改和刪除操作不會直接修改HFile,而是追加新的檔案,所以只要HFile還在,對應的block cache就是不變的。

2. block cache查詢不到再去查詢region(memstore + hfile):通過hbase的後設資料表,找到需要查詢的rowkey所在的region server,從而定位到memstore和hfile

6.2 region的查詢過程

HBase在移動廣告監測產品中的應用

圖:region的查詢過程

一個表有多個region,分佈在不同機器上,需要一定的機制來確定需要查詢的region

  • 通過zk找到meta所在的sever:meta表的位置儲存在zk中,meta中儲存了每個region的rowkey範圍,以及region所在的位置

  • 通過meta查詢出需要查詢的region所在的伺服器

  • 到伺服器上進行查詢

客戶端會對meta資訊進行快取,加快查詢速度。

6.3 查詢API

  • get:查詢某個rowkey對應的列

  • scan:指定rowkey範圍的掃描(setStartRow, setStopRow)

  • filter:scan過程中,對內容進行過濾

其中指定rowkey範圍是最有效的加快查詢速度的方式,不限定rowkey的範圍則需要全表掃

7 Ad Tracking的HBase設計

rowkey結構:分割槽key-pid-eventTime-spreadid-序列

  • 分割槽key:應用的唯一key(隨機字串)的hashcode / hbase的region個數

  • pid:應用的自增唯一主鍵

  • eventTime:事件的時間

  • spreadid:推廣活動的自增唯一主鍵

  • 序列:隨機序列,保證上述欄位相同的事件不會覆蓋寫入

Ad Tracking的hbase的rowkey是按照業務欄位來設計的,相同應用的資料儲存在同一個region中,查詢快,但是由於使用者的資料量不同,查詢量也不同,可能導致熱點資料,造成某臺機器負載過高,影響機群正常工作。目前Ad Tracking的HBase的各個region空間佔用尚存在一定程度的不均衡,但是還能接受。

一般HBase的rowkey中或多或少的會包含業務相關的資訊,完全採用隨機的rowkey,跟業務不相關,查詢的時候只能全表掃,查詢效率低。rowkey設計的關鍵就在於權衡查詢速度和資料均衡之間的關係,下面介紹幾方面rowkey的設計建議。

7.1 rowkey長度設計建議

  • 資料的持久化檔案 HFile 中是按照 KeyValue 儲存的,如果 rowkey 過長,比如超過 100 位元組,1000w 行資料,光 rowkey 就要佔用 100*1000w=10 億個位元組,將近 1G 資料,這樣會極大影響 HFile 的儲存效率;

  • MemStore 將快取部分資料到記憶體,如果 rowkey 欄位過長,記憶體的有效利用率就會降低,系統不能快取更多的資料,這樣會降低檢索效率;

  • 目前作業系統大都是 64 位系統,記憶體 8 位元組對齊,rowkey長度建議控制在 16 個位元組(8 位元組的整數倍),充分利用作業系統的最佳特性。

7.2 rowkey設計方式-加鹽

HBase在移動廣告監測產品中的應用

圖:rowkey設計方式-加鹽

使用固定的隨機字首:

  • 優點:資料均衡

  • 缺點:因為字首是隨機的,所以無法快速get;而scan的速度還可以

7.3 rowkey設計方式-hash

HBase在移動廣告監測產品中的應用

圖:rowkey設計方式-雜湊

rowkey hash之後取md5的前五位:

  • 優點:打散資料,字首在查詢的時候能通過rowkey得到,可以很快get

  • 缺點:相同字首的rowkey被打散,scan變慢

7.4 rowkey設計方式-反轉

HBase在移動廣告監測產品中的應用

圖:rowkey設計方式-反轉

反轉一段固定長度的rowkey,或者整個反轉。上圖中三個網址屬於相同域名下的,但是如果不反轉,會完全分散到不同的region中,不利於查詢。

end

參考資料

- [hbase-io-hfile-input-output](http://blog.cloudera.com/blog/2012/06/hbase-io-hfile-input-output/)

- [深入理解HBase的系統架構](https://blog.csdn.net/Yaokai_AssultMaster/article/details/72877127)

- [HBase底層儲存原理](https://www.cnblogs.com/panpanwelcome/p/8716652.html)

- [HBase – 探索HFile索引機制](http://hbasefly.com/2016/04/03/hbase_hfile_index/)

- [HBase – 儲存檔案HFile結構解析](

http://hbasefly.com/2016/03/25/hbase-hfile/)

作者: TalkingData 戰鵬弘



相關文章