摘要: 本文主要介紹了hbase對數據壓縮,編碼的支持,以及雲hbase在社區基礎上對數據壓縮率和訪問速度上了進行的改進。
前言
你可曾遇到這種需求,只有幾百qps的冷數據緩存,卻因為存儲水位要浪費幾十台服務器?你可曾遇到這種需求,幾百G的表,必須純cache命中,性能才能滿足業務需求?你可曾遇到,幾十M的小表,由於qps過高,必須不停的split,balance,利用多台服務器來抗熱點?
面對繁雜的場景,Ali-HBase團隊一直致力於為業務提供更多的選擇和更低的成本。本文主要介紹了hbase目前兩種提高壓縮率的主要方法:壓縮和DataBlockEncoding。
無損壓縮:更小,更快,更省資源
通用壓縮作為數據庫解決存儲的重要手段,通常數據庫都存在數據塊的概念,針對每個塊做壓縮和解壓。塊越大,壓縮率越高,scan throughput增加;塊越小,隨機讀IO壓力較小,讀latency越小。作為一種Tradeoff,線上hbase通常采用64K塊大小,在cache中不做壓縮,僅在落盤和讀盤時做壓縮和解壓操作。
開源hbase通常使用的LZO壓縮或者Snappy壓縮。這兩種壓縮的共同特點是都追求較高的壓縮解壓速度,並實現合理的數據壓縮率。然而,隨着業務的快速增漲,越來越多的業務因為因為存儲水位問題而擴容。hbase針對這一情況,采用了基於跨集群分區恢復技術的副本數優化、機型升級等方法,但依然無法滿足存儲量的快速膨脹,因此我們一直致力於尋找壓縮更高的壓縮方式。
新壓縮(zstd、lz4)上線
Zstandard(縮寫為Zstd)是一種新的無損壓縮算法,旨在提供快速壓縮,並實現高壓縮比。它既不像LZMA和ZPAQ那樣追求盡可能高的壓縮比,也不像LZ4那樣追求極致的壓縮速度。這種算法的壓縮速度超過200MB/s, 解壓速度超過400MB/s(實驗室數據),基本可以滿足目前hbase對吞吐量的需求。經驗證,Zstd的數據壓縮率相對於Lzo基本可以提高25%-30%,對於存儲型業務,這就意味着三分之一到四分之一的的成本減少。
而在另一種情況下,部分表存儲量較小,但qps大,對rt要求極高。針對這種場景,我們引入了lz4壓縮,其解壓速度在部分場景下可以達到lzo的兩倍以上。一旦讀操作落盤需要解壓縮,lz4解壓的rt和cpu開銷都明顯小於lzo壓縮。
我們先通過一張圖片直觀的展示各種壓縮算法的性能:
以線上幾種典型數據場景為例,看看幾種壓縮的實際壓縮率和單核解壓速度(以下數據均來自於實際應用)
業務類型 | 無壓縮表大小 | LZO(壓縮率/解壓速度MB/s) | ZSTD(壓縮率/解壓速度MB/s) | LZ4(壓縮率/解壓速度MB/s) |
---|---|---|---|---|
監控類 | 419.75T | 5.82/372 | 13.09/256 | 5.19/463.8 |
日志類 | 77.26T | 4.11/333 | 6.0/287 | 4.16/ 496.1 |
風控類 | 147.83T | 4.29/297.7 | 5.93/270 | 4.19/441.38 |
消費類 | 108.04T | 5.93/316.8 | 10.51/288.3 | 5.55/520.3 |
目前,2017年雙11,ZSTD已經在線上全面鋪開,已累計優化存儲數PB。LZ4也已經在部分讀要求較高業務上線。
下圖為某監控類應用zstd壓縮算法后,集群整體存儲量的下降情況。數據量由100+T減少到75T。
編碼技術:針對結構化數據的即查即解壓
hbase作為一種schema free的數據庫,相當於傳統的關系型數據庫更加靈活,用戶無需設計好表的結構,也可以在同一張表內寫入不同schema的數據。然而,由於缺少數據結構的支持,hbase需要很多額外的數據結構來標注長度信息,且無法針對不同的數據類型采用不同的壓縮方式。針對這一問題,hbase提出了編碼功能,用來降低存儲開銷。由於編碼對cpu開銷較小,且效果較好,通常cache中也會開啟編碼功能。
舊DIFF Encoding介紹
hbase很早就支持了DataBlockEncoding,也就是是通過減少hbase keyvalue中重復的部分來壓縮數據。 以線上最常見的DIFF算法為例,某kv壓縮之后的結果:
- 一個字節的flag(這個flag的作用后面解釋)
- 如果和上個KV的鍵長不一樣,則寫入1~5個字節的長度
- 如果和上個KV的值長不一樣,則寫入1~5個字節的長度
- 記錄和上個KV鍵相同的前綴長度,1~5個字節
- 非前綴部分的row key
- 如果是第一條KV,寫入列族名
- 非前綴部分的的列名
- 寫入1~8字節的timestamp或者與上個KV的timestamp的差(是原值還是寫與上個KV的差,取決於哪個字節更小)
- 如果和上個KV的type不一樣,則寫入1字節的type(Put,Delete)
- Value內容
那么在解壓縮時,怎么判斷和上個KV的鍵長是否一樣,值長是否一樣,寫入的時間戳究竟是是原值還是差值呢?這些都是通過最早寫入的1個字節的flag來實現的,
這個字節中的8位bit,含義是:
- 第0位,如果為1,鍵長與上個kv相等
- 第1位,如果為1,值長與上個kv相等
- 第2位,如果為1,type與上個kv一樣
- 第3位,如果為1,則寫入的timestamp是差值,否則為原值
- 第456位,這3位組合起來的值(能表示0~7),表示寫入的時間戳的長度
- 第7位,如果為1,表示寫入的timestamp差值為負數,取了絕對值。
DIFF 編碼之后,對某個文件的seek包含以下兩步:
- 通過index key找到對應的datablock
- 從第一個完整KV開始,順序查找,不斷decode下一個kv,直到找到目標kv為止。
DIFF encoding對小kv場景使用效果較好,可以減少2-5倍的數據量。
新Indexable Delta Encoding上線
從性能角度考慮,hbase通常需要將Meta信息裝載進block cache。如果將block大小較小,Meta信息較多,會出現Meta無法完全裝入Cache的情況, 性能下降。如果block大小較大,DIFF Encoding順序查詢的性能會成為隨機讀的性能瓶頸。針對這一情況,我們開發了Indexable Delta Encoding,在block內部也可以通過索引進行快速查詢,seek性能有了較大提高。Indexable Delta Encoding原理如圖所示:
在通過BlockIndex找到對應的數據塊后,我們從數據塊末尾找到每個完整KV的offset,並利用二分查找快速定位到符合查詢條件的完整kv,再順序decode每一個Diff kv,直到找到目標kv位置。
通過Indexable Delta Encoding, HFile的隨機seek性能相對於使用之前翻了一倍,以64K block為例,在全cache命中的隨機Get場景下,相對於Diff encoding rt下降50%,但存儲開銷僅僅提高3-5%。Indexable Delta Encoding目前已在線上多個場景應用,經受了雙十一的考驗,整體平均讀rt減少10%-15%。
雲端使用
阿里HBase目前已經在阿里雲提供商業化服務,任何有需求的用戶都可以在阿里雲端使用深入改進的、一站式的HBase服務。雲HBase版本與自建HBase相比在運維、可靠性、性能、穩定性、安全、成本等方面均有很多的改進,更多內容歡迎大家關注 https://www.aliyun.com/product/hbase
轉自:https://yq.aliyun.com/articles/277084
交流
如果大家對HBase有興趣,致力於使用HBase解決實際的問題,歡迎加入Hbase技術社區群交流:
微信HBase技術社區群,假如微信群加不了,可以加秘書微信: SH_425 ,然后邀請您。
釘釘HBase技術社區群