1、what:什么是HBase
HBase的原型是Google的BigTable論文,受到了該論文思想的啟發,目前作為Hadoop的子項目來開發維護,用於支持結構化的數據存儲。
HBase是一個高可靠性、高性能、面向列、可伸縮的分布式存儲系統,利用HBASE技術可在廉價PC Server上搭建起大規模結構化存儲集群。
HBase的目標是存儲並處理大型的數據,更具體來說是僅需使用普通的硬件配置,就能夠處理由成千上萬的行和列所組成的大型數據。【非大勿用】
HBase是Google Bigtable的開源實現,但是也有很多不同之處。比如:Google Bigtable利用GFS作為其文件存儲系統,HBase利用Hadoop HDFS作為其文件存儲系統;Google運行MAPREDUCE來處理Bigtable中的海量數據,HBase同樣利用Hadoop MapReduce來處理HBase中的海量數據;Google Bigtable利用Chubby作為協同服務,HBase利用Zookeeper作為對應。
上面的話太官方,挨個看都認識,連起來不理解。簡單粗暴的總結:就是一款NoSQL數據庫,面向列存儲,用於存儲處理海量數據。
核心在於它是一個存數據的地方,可是在此之前學習過了HDFS和Mysql,那HBase為什么還會出現呢?后邊細說~
2、why:為什么會有HBase?
先說一下Mysql,我們都知道Mysql是一個關系型數據庫,平時開發使用的非常頻繁。一個網站或者系統最核心的表就是用戶表,而當用戶表的數據達到幾千萬甚至幾億級別的時候,對單條數據的檢索將會耗費數秒甚至分鍾級別。實際的清空可能更加復雜不堪。
看下邊一張表:

有這么一張用戶表,假如我要根據id=1查詢出來這條數據對應的用戶姓名,很簡單,會給我們返回zhangsan。但是,當我們查的時候,想一下,查名字的時候age和email會不會被查出來?答案是肯定的,Mysql的數據存儲是以行為單位的,面向行存儲。那問題就出現了,我只需要找出zhangsan的名字,卻需要查詢一整行的數據,如果列非常多,那么查詢效率可想而知了。
查詢的操作速度會受到以下兩個因素的制約:
- 表被並發的插入、編輯以及刪除操作。
- 查詢語句通常不是簡單的對一個表進行操作,有可能是多個表關聯后的復雜查詢,甚至有可能是group by或者order by操作,此時,性能下降很明顯。
如果一張表的列過多,會影響查詢效率,我們稱這樣表為寬表。怎么優化呢,拆開來,豎直拆分:

這樣的情況下,我們要查找username的時候只需要查找user_basic表,沒有多余的字段,查詢效率就會很快。
如果一張表的行過多,會影響查詢效率,我們將這樣的表稱之為高表,可以采用水平拆表的方式提高效率:

這種水平拆分應用比較多的 場景就是日志表,日志信息每天產生很多,可以按月進行水平拆分,這樣就實現了高表變矮。
ok,這種拆分方式貌似可以解決寬表和高表的問題,但是如果有一天公司的業務變了,比如原來沒有微信,現在有了微信,需要加入用戶的微信字段。這時候需要改變表的結構信息,該怎么辦?最簡單的想法是多加一列,像這樣:

多考慮一下就知道這樣做很不妥帖,比如說有些早期用戶沒有微信,這一列是設置默認值還是采取其他的做法就得權衡一下。如果需要擴展很多的列出來,而且不是所有的用戶都有這些屬性,那么拓展起來就更加復雜了。
這時候,想到了JSON格式的字符串,這是一種以字符串的形式表示的對象,而且屬性字段可以動態拓展,於是有了下邊這種做法,兩種做法加以對比:

ok,這樣存儲數據它不挺好的嘛,HBase出來干嘛??Mysql有一點,數據達到一定的閾值,無論怎么優化,它都無法達到高性能的發揮。而大數據領域的數據,動輒PB級,這種存儲應用明顯是不能很好的滿足需求的。針對上邊的問題,HBase都有很好的解決方案~~
3、How:HBase怎么實現的?
先不說為什么用,接着上邊說到的幾個問題:高表寬表,數據列動態擴展,把提到的幾個解決辦法:水平垂直切分,列擴展方法,雜糅在一起。
有這么一張表,怕它又寬又高,又會動態擴展列,那么在設計之初,就把這個表給他拆開,為了列的動態拓展,直接存儲JSON格式:

這樣就解決了寬表問題,高表怎么辦呢?
一個表的兩部分,各存一部分行:

解決了高表,寬表,動態擴展列的問題~~完美plus~
如果還要進一步提高性能怎么辦?Mysql->Redis !!! 緩存啊!
查詢出來的數據放入到緩存中,下一次查詢直接從緩存中拿數據。插入數據怎么辦呢?也可以這樣理解,我把要插入的數據放進緩存中,再也不用管了,直接由數據庫從緩存拿數據插入到數據庫。此時程序不需要等待數據插入成功,提高了並行工作的效率。
可是這樣做有了很大的風險,服務器宕機的話,緩存中的數據沒來得及插入到數據庫中,那不就丟數據了嘛。參考Redis的持久化策略,可以給插入數據這個操作添加一個操作日志,用於持久化插入操作,宕機重啟后從日志恢復。
這樣設計架構就變成了這個樣子:

上邊這種解決方式,實際上就是HBase實現的大致思路,詳細的內容會在后邊慢慢說。
簡單粗暴總結:HBase就是一個面向列存儲的非關系型數據庫。兩者的區別主要是:

HBase是的存儲時基於HDFS的,HDFS有着高容錯性的特點,被設計用來部署在低廉的硬件上,而且它提供高吞吐量以訪問應用程序的數據,時候那些有着超大數據集的應用程序。基於Hadoop意味着HBase與生俱來的超強的擴展性和吞吐量。
HBase采用的時key/value的存儲方式,這意味着,及時隨着數據量的增大,也幾乎不會導致查詢性能的下降。HBase又是一個面向列存儲的數據庫,當表的字段很多時,可以把其中幾個字段獨立出來放在一部分機器上,而另外幾個字段放到另一部分機器上,充分分散了負載的壓力。如此復雜的存儲結構和分布式的存儲方式,帶來的代價就是:即便是存儲很少的數據,也不會很快。
HBase並不是足夠快,而是數據量很大的時候它慢的不明顯。
什么時候使用HBase呢,主要是以下兩種情況:
- 單表數據量超過千萬,而且並發量很大;
- 數據分析需求較弱,或者不需要那么實時靈活。
參考資料:
[1] 李海波. 大數據技術之HBase
[2] 楊曦. HBase不睡覺書