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

一、HBase在Ad Tracking的應用

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

Ad Tracking是TalkingData的移動廣告監測產品,其核心業務模型是歸因。App用戶點擊廣告以後,及隨後安裝廣告跳轉到的應用或者遊戲,Ad Tracking會對這些點擊事件(用戶點擊廣告的行爲)和激活事件(用戶安裝應用的行爲)進行監測。算法

歸因須要作的是,接收到激活事件以後,經過激活事件匹配以前接收到的點擊事件,若是激活歸因到了點擊,那麼這個激活事件就是點擊廣告帶來的,也就歸因到了該廣告對應的推廣活動,而推廣活動對應某個渠道,歸因到了推廣活動就歸因到了投放廣告的渠道等。後續的全部效果點事件(例如應用內的註冊、登陸等事件)也都將經過對應的激活事件找到對應的推廣活動信息。數組

激活和各類效果點事件的原始信息,包括對應的設備、歸因到的推廣活動等,均可以提供給Ad Tracking用戶爲參考——Ad Tracking的數據導出功能。緩存

1.2 HBase與數據導出服務器

HBase做爲一個分佈式的列式存儲,擁有強悍的數據寫入能力,因爲是列式存儲,隨着後期需求的增長,能夠動態的增長存儲的字段,很是契合Ad Tracking的數據導出的業務場景。架構

經過合理的設計rowkey,HBase又能保證很快的查詢速度,用戶在Ad Tracking後臺進行數據導出以後,基本上秒級時間就可以完成數據的下載,可以保證很好的導出體驗。分佈式

下面將對HBase的架構原理和Ad Tracking數據導出功能中的應用進行介紹下。性能

二、HBase的架構

圖:HBase的基本架構操作系統

  • master:.net

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

    ▫region的分配,merge,分割

  • zookeeper:

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

    ▫master的HA

    ▫記錄HBase的元數據信息的存儲位置

  • region server:數據的寫入與查詢

  • hdfs:數據的存儲,region不直接跟磁盤打交道,經過hdfs實現數據的落盤和讀取

三、數據的寫入

3.1 數據的寫入過程

圖:數據的寫入概覽

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

  • MemStore:數據進入內存,按照rowkey進行排序

  • HFile:MemStore中的數據到達必定量或者必定時間,建立HFile落盤

3.二、數據格式

HBase存儲的全部內容都是byte數組,因此只要能轉化成byte數組的數據均可以存儲在HBase中。

四、存儲模型

圖:HBase的存儲概念模型

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

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

  • 列族:列族包含若干列,這些列在物理上存儲在一塊兒,因此列族內的列通常是在查詢的時候須要一塊兒讀取。數據的屬性,例如超時時間、壓縮算法等,都須要在列族上定義

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

  • 單元格:列的內容保存在單元格中,若是有過更新操做,會有多個版本

五、存儲實現

圖: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到磁盤中,隨着磁盤中的小文件的增多,後臺進行會自動進行合併,過多的小文件合併爲一個大文件,可以有效加快查詢速度。

圖: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.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的查找過程

圖: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設計方式-加鹽

圖:rowkey設計方式-加鹽

使用固定的隨機前綴:

  • 優勢:數據均衡

  • 缺點:由於前綴是隨機的,因此沒法快速get;而scan的速度還能夠

7.3 rowkey設計方式-hash

圖:rowkey設計方式-哈希

rowkey hash以後取md5的前五位:

  • 優勢:打散數據,前綴在查詢的時候能經過rowkey獲得,能夠很快get

  • 缺點:相同前綴的rowkey被打散,scan變慢

7.4 rowkey設計方式-反轉

圖: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 戰鵬弘

相關文章
相關標籤/搜索