HBase—基础介绍
原文作者:Java3
原文地址:我終于看懂了HBase,太不容易了...
目錄
摘要:
前言
一、介紹HBase
二、為什么要用HBase
三、入門HBase
3.1 HBase的數據模型
3.2 HBase 的Key-Value
3.3 HBase架構
3.4 HRegionServer內部
3.5 被遺忘的HMaster
四、RowKey的設計
4.1 根據一個RowKey查詢
4.2根據RowKey范圍查詢
摘要:
- HBase是一個NoSQL數據庫,一般我們用它來存儲海量的數據
- HBase在HDFS之上提供了高并發的隨機寫和支持實時查詢,MySql是單機的不支持大數據,Kafka不支持隨機讀取,Redis數據存儲在內存太貴,Elasticsearch的檢索功能消耗性能,HDFS不支持隨機修改和小文件
- HBase的特點是:可以以低成本來存儲海量的數據并且支持高并發隨機寫和實時查詢,且存儲數據的”結構“可以地非常靈活
- 數據讀寫流程:client請求到Zookeeper,然后Zookeeper返回HRegionServer地址給client,client得到Zookeeper返回的地址去請求HRegionServer,HRegionServer讀寫數據后返回給client
前言
在我還不了解分布式和大數據的時候已經聽說過HBase了,但對它一直都半知不解,這篇文章來講講吧。在真實生活中,最開始聽到這個詞是我的一場面試,當年我還是個『小垃圾』,現在已經是個『大垃圾』了。面試官當時給了一個場景題問我,具體的題目我忘得差不多了,大概就是考試與試題的一個場景,問我數據庫要如何設計。我答了關系型數據庫的設計方案,他大概說:這個場景比較復雜多變,為什么不考慮一下HBase這種NoSQL的數據庫來存儲呢?我就說:“對對對,可以的” (雖然我當時不知道HBase是什么,但是氣勢一定要有,你們說是不是)最后面試官還是給我發了offer,但我沒去,原因就是離家太遠了。
一、介紹HBase
Apache?HBase? is the?Hadoop?database, a distributed, scalable, big data store.HBase is a type of "NoSQL" database.
Apache HBase 是 Hadoop 數據庫,一個分布式、可伸縮的大數據存儲。HBase是依賴Hadoop的。為什么HBase能存儲海量的數據?因為HBase是在HDFS的基礎之上構建的,HDFS是分布式文件系統。
二、為什么要用HBase
截至到現在,三歪已經學了不少的組件了,比如說分布式搜索引擎「Elasticsearch」、分布式文件系統「HDFS」、分布式消息隊列「Kafka」、緩存數據庫「Redis」等等,為什么我們還要用HBase呢?雖然沒有什么可比性,但是在學習的時候總會有一個疑問:「既然已學過的系統都有類似的功能了,那為啥我還要去學這個玩意?」三歪是這樣理解的:
- MySQL?MySQL數據庫我們是算用得最多了的吧?但眾所周知,MySQL是單機的。MySQL能存儲多少數據,取決于那臺服務器的硬盤大小。以現在互聯網的數據量,很多時候MySQL是沒法存儲那么多數據的。比如我這邊有個系統,一天就能產生1TB的數據,這數據是不可能存MySQL的。(如此大的量數據,我們現在的做法是先寫到Kafka,然后落到Hive中)
- Kafka?Kafka我們主要用來處理消息的(解耦異步削峰)。數據到Kafka,Kafka會將數據持久化到硬盤中,并且Kafka是分布式的(很方便的擴展),理論上Kafka可以存儲很大的數據。但是Kafka的數據我們不會「單獨」取出來。持久化了的數據,最常見的用法就是重新設置offset,做「回溯」操作
- Redis?Redis是緩存數據庫,所有的讀寫都在內存中,速度賊快。AOF/RDB存儲的數據都會加載到內存中,Redis不適合存大量的數據(因為內存太貴了!)。
- Elasticsearch?Elasticsearch是一個分布式的搜索引擎,主要用于檢索。理論上Elasticsearch也是可以存儲海量的數據(畢竟分布式),我們也可以將數據用『索引』來取出來,似乎已經是非常完美的中間件了。但是如果我們的數據沒有經常「檢索」的需求,其實不必放到Elasticsearch,數據寫入Elasticsearch需要分詞,無疑會浪費資源。
- HDFS?顯然HDFS是可以存儲海量的數據的,它就是為海量數據而生的。它也有明顯的缺點:不支持隨機修改,查詢效率低,對小文件支持不友好。
上面這些技術棧三歪都已經寫過文章了。學多了你會發現它們的持久化機制都差不太多,有空再來總結一下。
文中的開頭已經說了,HBase是基于HDFS分布式文件系統去構建的。換句話說,HBase的數據其實也是存儲在HDFS上的。那肯定有好奇寶寶就會問:HDFS和HBase有啥區別阿?HDFS是文件系統,而HBase是數據庫,其實也沒啥可比性。「你可以把HBase當做是MySQL,把HDFS當做是硬盤。HBase只是一個NoSQL數據庫,把數據存在HDFS上」。
數據庫是一個以某種有組織的方式存儲的數據集合。
扯了這么多,那我們為啥要用HBase呢?HBase在HDFS之上提供了高并發的隨機寫和支持實時查詢,這是HDFS不具備的。我一直都說在學習某一項技術之前首先要了解它能干什么。如果僅僅看上面的”對比“,我們可以發現HBase可以以低成本來存儲海量的數據并且支持高并發隨機寫和實時查詢。但HBase還有一個特點就是:存儲數據的”結構“可以地非常靈活(這個下面會講到,這里如果沒接觸過HBase的同學可能不知道什么意思)。
三、入門HBase
聽過HBase的同學可能都聽過「列式存儲」這個詞。我最開始的時候覺得HBase很難理解,就因為它這個「列式存儲」我一直理解不了它為什么是「列式」的。在網上也有很多的博客去講解什么是「列式」存儲,它們會舉我們現有的數據庫,比如MySQL。存儲的結構我們很容易看懂,就是一行一行數據嘛。
轉換成所謂的列式存儲是什么樣的呢?
可以很簡單的發現,無非就是把每列抽出來,然后關聯上Id。這個叫列式存儲嗎?我在這打個問號。轉換后的數據從我的角度來看,數據還是一行一行的。這樣做有什么好處嗎?很明顯以前我們一行記錄多個屬性(列),有部分的列是空缺的,但是我們還是需要空間去存儲。現在把這些列全部拆開,有什么我們就存什么,這樣空間就能被我們充分利用。這種形式的數據更像什么?明顯是Key-Value嘛。那我們該怎么理解HBase所謂的列式存儲和Key-Value結構呢?走進三歪的小腦袋,一探究竟。
3.1 HBase的數據模型
在看HBase數據模型的時候,其實最好還是不要用「關系型數據庫」的知識去理解它。
In HBase, data is stored in tables, which have rows and columns. This is a terminology overlap withrelational databases (RDBMSs),?but this is not a helpful analogy.
HBase里邊也有表、行和列的概念。
- 表沒什么好說的,就是一張表
- 一行數據由一個行鍵和一個或多個相關的列以及它的值所組成
好了,現在比較抽象了。在HBase里邊,定位一行數據會有一個唯一的值,這個叫做行鍵(RowKey)。而在HBase的列不是我們在關系型數據庫所想象中的列。HBase的列(Column)都得歸屬到列族(Column Family)中。在HBase中用列修飾符(Column Qualifier)來標識每個列。在HBase里邊,先有列族,后有列。什么是列族?可以簡單理解為:列的屬性類別.什么是列修飾符?先有列族后有列,在列族下用列修飾符來標識一列。還很抽象是不是?三歪來畫個圖:
我們再放點具體的值去看看,就更加容易看懂了:
這張表我們有兩個列族,分別是UserInfo和OrderInfo。在UserInfo下有兩個列,分別是UserInfo:name和UserInfo:age,在OrderInfo下有兩個列,分別是OrderInfo:orderId和OrderInfo:money。UserInfo:name的值為:三歪。UserInfo:age的值為24。OrderInfo:orderId的值為23333。OrderInfo:money的值為30。這些數據的主鍵(RowKey)為1上面的那個圖看起來可能不太好懂,我們再畫一個我們比較熟悉的:
HBase表的每一行中,列的組成都是靈活的,行與行之間的列不需要相同。如圖下:
換句話說:一個列族下可以任意添加列,不受任何限制。數據寫到HBase的時候都會被記錄一個時間戳,這個時間戳被我們當做一個版本。比如說,我們修改或者刪除某一條的時候,本質上是往里邊新增一條數據,記錄的版本加一了而已。比如現在我們有一條記錄:
?
現在要把這條記錄的值改為40,實際上就是多添加一條記錄,在讀的時候按照時間戳讀最新的記錄。在外界「看起來」就是把這條記錄改了。
3.2 HBase 的Key-Value
HBase本質上其實就是Key-Value的數據庫,上一次我們學Key-Value數據庫還是Redis呢。那在HBase里邊,Key是什么?Value是什么?我們看一下下面的HBaseKey-Value結構圖:
?
Key由RowKey(行鍵)+ColumnFamily(列族)+Column Qualifier(列修飾符)+TimeStamp(時間戳--版本)+KeyType(類型)組成,而Value就是實際上的值。對比上面的例子,其實很好理解,因為我們修改一條數據其實上是在原來的基礎上增加一個版本的,那我們要準確定位一條數據,那就得(RowKey+Column+時間戳)。KeyType是什么?我們上面只說了「修改」的情況,你們有沒有想過,如果要刪除一條數據怎么做?實際上也是增加一條記錄,只不過我們在KeyType里邊設置為“Delete”就可以了。
3.3 HBase架構
扯了這么一大堆,已經說了HBase的數據模型和Key-Value了,我們還有一個問題:「為什么經常會有人說HBase是列式存儲呢?」其實HBase更多的是「列族存儲」,要談列族存儲,就得先了解了解HBase的架構是怎么樣的。我們先來看看HBase的架構圖:
總結大致的流程就是:client請求到Zookeeper,然后Zookeeper返回HRegionServer地址給client,client得到Zookeeper返回的地址去請求HRegionServer,HRegionServer讀寫數據后返回給client。
3.4 HRegionServer內部
我們來看下面的圖:
前面也提到了,HBase可以存儲海量的數據,HBase是分布式的。所以我們可以斷定:HBase一張表的數據會分到多臺機器上的。那HBase是怎么切割一張表的數據的呢?用的就是RowKey來切分,其實就是表的橫向切割。
說白了就是一個HRegion上,存儲HBase表的一部分數據。
HRegion下面有Store,那Store是什么呢?我們前面也說過,一個HBase表首先要定義列族,然后列是在列族之下的,列可以隨意添加。一個列族的數據是存儲在一起的,所以一個列族的數據是存儲在一個Store里邊的。看到這里,其實我們可以認為HBase是基于列族存儲的(畢竟物理存儲,一個列族是存儲到同一個Store里的)
Store里邊有啥?有Mem Store、Store File、HFile,我們再來看看里邊都代表啥含義。
HBase在寫數據的時候,會先寫到Mem Store,當MemStore超過一定閾值,就會將內存中的數據刷寫到硬盤上,形成StoreFile,而StoreFile底層是以HFile的格式保存,HFile是HBase中KeyValue數據的存儲格式。所以說:Mem Store我們可以理解為內存 buffer,HFile是HBase實際存儲的數據格式,而StoreFile只是HBase里的一個名字。回到HRegionServer上,我們還漏了一塊,就是HLog。
這里其實特別好理解了,我們寫數據的時候是先寫到內存的,為了防止機器宕機,內存的數據沒刷到磁盤中就掛了。我們在寫Mem store的時候還會寫一份HLog。這個HLog是順序寫到磁盤的,所以速度還是挺快的(是不是有似曾相似的感覺)...稍微總結一把:
- HRegionServer是真正干活的機器(用于與hdfs交互),我們HBase表用RowKey來橫向切分表
- HRegion里邊會有多個Store,每個Store其實就是一個列族的數據(所以我們可以說HBase是基于列族存儲的)
- Store里邊有Men Store和StoreFile(HFile),其實就是先走一層內存,然后再刷到磁盤的結構
3.5 被遺忘的HMaster
我們在上面的圖會看到有個Hmaster,它在HBase的架構中承擔一種什么樣的角色呢?讀寫請求都沒經過Hmaster呀。
那HMaster在HBase里承擔什么樣的角色呢??
HMaster?is the implementation of the Master Server. The Master server is responsible for monitoring all RegionServer instances in the cluster, and is the interface for all metadata changes.
HMaster會處理 HRegion 的分配或轉移。如果我們HRegion的數據量太大的話,HMaster會對拆分后的Region重新分配RegionServer。(如果發現失效的HRegion,也會將失效的HRegion分配到正常的HRegionServer中)HMaster會處理元數據的變更和監控RegionServer的狀態。
四、RowKey的設計
到這里,我們已經知道RowKey是什么了。不難理解的是,我們肯定是要保證RowKey是唯一的,畢竟它是行鍵,有了它我們才可以唯一標識一條數據的。在HBase里邊提供了三種的查詢方式:
4.1 根據一個RowKey查詢
首先我們要知道的是RowKey是會按字典序排序的,我們HBase表會用RowKey來橫向切分表。無論是讀和寫我們都是用RowKey去定位到HRegion,然后找到HRegionServer。這里有一個很關鍵的問題:那我怎么知道這個RowKey是在這個HRegion上的?HRegion上有兩個很重要的屬性:start-key和end-key。我們在定位HRegionServer的時候,實際上就是定位我們這個RowKey在不在這個HRegion的start-key和end-key范圍之內,如果在,說明我們就找到了。這個時候會帶來一個問題:由于我們的RowKey是以字典序排序的,如果我們對RowKey沒有做任何處理,那就有可能存在熱點數據的問題。舉個例子,現在我們的RowKey如下:
java3y111 java3y222 java3y333 java3y444 java3y555 aaa bbb java3y777 java3y666 java3y...Java3yxxx開頭的RowKey很多,而其他的RowKey很少。如果我們有多個HRegion的話,那么存儲Java3yxxx的HRegion的數據量是最大的,而分配給其他的HRegion數量是很少的。關鍵是我們的查詢也幾乎都是以java3yxxx的數據去查,這會導致某部分數據會集中在某臺HRegionServer上存儲以及查詢,而其他的HRegionServer卻很空閑。如果是這種情況,我們要做的是什么?對RowKey散列就好了,那分配到HRegion的時候就比較均勻,少了熱點的問題。
HBase優化手冊:建表申請時的預分區設置,對于經常使用HBase的小伙伴來說,HBase管理平臺里申請HBase表流程必然不陌生了。'給定split的RowKey組例如:aaaaa,bbbbb,ccccc;或給定例如:startKey=00000000,endKey=xxxxxxxx,regionsNum=x'?
第一種方式:?是自己指定RowKey的分割點來劃分region個數.比如有一組數據RowKey為[1,2,3,4,5,6,7],此時給定split RowKey是3,6,那么就會劃分為[1,3),[3,6),[6,7)的三個初始region了.如果對于RowKey的組成及數據分布非常清楚的話,可以使用這種方式精確預分區.
第二種方式?:如果只是知道RowKey的組成大致的范圍,可以選用這種方式讓集群來均衡預分區,設定始末的RowKey,以及根據數據量給定大致的region數,一般建議region數最多不要超過集群的rs節點數,過多region數不但不能增加表訪問性能,反而會增加master節點壓力.如果給定始末RowKey范圍與實際差較大的話,還是比較容易產生數據熱點問題.
最后:生成RowKey時,盡量進行加鹽或者哈希的處理,這樣很大程度上可以緩解數據熱點問題.
4.2根據RowKey范圍查詢
上面的情況是針對通過RowKey單個查詢的業務的,如果我們是根據RowKey范圍查詢的,那沒必要上面那樣做。HBase將RowKey設計為字典序排序,如果不做限制,那很可能類似的RowKey存儲在同一個HRegion中。那我正好有這個場景上的業務,那我查詢的時候不是快多了嗎?在同一個HRegion就可以拿到我想要的數據了。舉個例子:我們會間隔幾秒就采集直播間熱度,將這份數據寫到HBase中,然后業務方經常要把主播的一段時間內的熱度給查詢出來。我設計好的RowKey,將該主播的一段時間內的熱度都寫到同一個HRegion上,拉取的時候只要訪問一個HRegionServer就可以得到全部我想要的數據了,那查詢的速度就快很多。
最后
最后三歪再來帶著大家回顧一下這篇文章寫了什么:
參考資料:
- https://blog.csdn.net/bitcarmanlee/article/details/78979836
- https://hbase.apache.org/book.html#arch.overview
- https://zhuanlan.zhihu.com/p/54184168
- 硬核干貨長文!Hbase來了解一下不?
- https://www.jianshu.com/p/569106a3008f
- 趣談Hbase架構
- https://www.cnblogs.com/BIG-BOSS-ZC/p/11807304.html
- 一條數據的HBase之旅,簡明HBase入門教程-開篇
- https://chenhy.com/post/hbase-quickstart/
- https://www.cnblogs.com/zmoumou/p/10292676.html
- https://www.cnblogs.com/duanxz/p/3154487.html
- https://www.jianshu.com/p/4e412f48e820
- HBase 基本入門篇
- 什么是列式存儲?
各類知識點總結
下面的文章都有對應的原創精美PDF,在持續更新中,可以來找我催更~
- 92頁的Mybatis
- 129頁的多線程
- 141頁的Servlet
- 158頁的JSP
- 76頁的集合
- 64頁的JDBC
- 105頁的數據結構和算法
- 142頁的Spring
- 58頁的過濾器和監聽器
- 30頁的HTTP
- 42頁的SpringMVC
- Hibernate
- AJAX
- Redis
- ......
涵蓋Java后端所有知識點的開源項目(已有8K+ star):
- GitHub
- Gitee訪問更快
如果大家想要實時關注我更新的文章以及分享的干貨的話,微信搜索Java3y。PDF文檔的內容均為手打,有任何的不懂都可以直接來問我(公眾號有我的聯系方式)。
給三歪點個贊,對三歪真的非常重要!
總結
以上是生活随笔為你收集整理的HBase—基础介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分布式离线计算—HiveSQL
- 下一篇: 软件设计模式—面向接口编程