又是一週,這次給自己複習一下Hbase,算是寫的比較詳細的,當然比較晚了,還沒寫完,這兩天一定抽時間把它補完。
接下來進入正題:
1、Hbase的介紹
之前我們熟悉的數據庫,比如Mysql,屬於是關係型數據庫,但是它的單機單表的數據量還是有限,在700—1000萬條(網查的),但是在大數據框架中,這點數據量還是捉襟見肘,所以採用NOSQL數據庫
關係型數據庫:例如mysql、 Oracle
非關係型數據庫:HBase
注意:Hbase讀比寫慢,詳情請看Hbase的讀與寫流程
2、Hbase的安裝與配置
首先需要知道:Hbase的存儲是基於HDFS的,並且Hbase的元數據信息也存儲在Zookeeper中,所以zk與hadoop需要能夠正常啓動。
2.1 Zookeeper與Hadoop正常部署
zookeeper集羣的啓動:zk.sh start
Hadoop集羣的正常部署並啓動:hdfs.sh start
幫助提示:
zk的啓動命令:bin/zkServer.sh start
hdfs服務的啓動:sbin/start-dfs.sh
yarn啓動:sbin/start-yarn.sh
2.2 HBase的解壓
解壓Hbase到指定目錄:tar -zxvf hbase-1.3.1-bin.tar.gz -C /usr/local/
Hbase-1.3.1的安裝包:
2.3 HBase的配置文件
修改HBase對應的配置文件,位置:hbase的conf目錄下:
1)hbase-env.sh修改內容(配置環境變量):
export JAVA_HOME=/usr/local/opt/jdk1.8.0_144
export HBASE_MANAGES_ZK=false
這是因爲Hbase裏面有一個內置的zookeeper,所以我們在這裏關閉,使用我們自己的zookeeper集羣
2)hbase-site.xml添加以下內容:
<configuration>
<!-- 配置Hbase的數據存儲地址-->
<property>
<name>hbase.rootdir</name>
<value>hdfs://master102:9000/HBase</value>
</property>
<!-- 配置Hbase的集羣分佈式爲true -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- 0.98後的新變動,之前版本沒有.port,默認端口爲60000 -->
<property>
<name>hbase.master.port</name>
<value>16000</value>
</property>
<!-- 配置zookeeper的集羣 -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>master102,slaver103,slaver104</value>
</property>
<!-- 配置Hbase在zookeeper中存儲數據的目錄(存儲元數據信息) -->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/usr/local/zookeeper-3.4.10/zkData</value>
</property>
</configuration>
3)regionservers(配置hbase集羣的節點):
master102
slaver103
slaver104
4)軟連接hadoop配置文件到HBase:
ln -s /usr/local/hadoop-2.7.2/etc/hadoop/core-site.xml /usr/local/hbase/conf/core-site.xml
ln -s /usr/local/hadoop-2.7.2/etc/hadoop/hdfs-site.xml /usr/local/hbase/conf/hdfs-site.xml
2.4 HBase遠程發送到其他集羣
[later@master module]$ xsync hbase/
同步服務請參考:
2.5 Hbase服務的啓動
1.啓動方式
[later@master hbase]$ bin/hbase-daemon.sh start master
[later@master hbase]$ bin/hbase-daemon.sh start regionserver
2.啓動方式2
[later@master hbase]$ bin/start-hbase.sh
停止服務:
[later@master hbase]$ bin/stop-hbase.sh
特別注意:如果集羣之間的節點時間不同步,會導致regionserver無法啓動,拋出ClockOutOfSyncException異常。集羣時間同步請參考:
2.6 查看Hbase頁面
http://master102:16010
2.7 HBase Shell基本測試
1.進入HBase客戶端命令行
[later@master hbase]$ bin/hbase shell
2.查看幫助命令
hbase(main):001:0> help
3.查看當前數據庫中有哪些表
hbase(main):002:0> list
1.創建表
hbase(main):002:0> create ‘student’,‘info’
2.插入數據到表
hbase(main):003:0> put ‘student’,‘1001’,‘info:sex’,‘male’
hbase(main):004:0> put ‘student’,‘1001’,‘info:age’,‘18’
hbase(main):005:0> put ‘student’,‘1002’,‘info:name’,‘Janna’
hbase(main):006:0> put ‘student’,‘1002’,‘info:sex’,‘female’
hbase(main):007:0> put ‘student’,‘1002’,‘info:age’,‘20’
3.掃描查看錶數據
hbase(main):008:0> scan ‘student’
hbase(main):009:0> scan ‘student’,{STARTROW => ‘1001’, STOPROW => ‘1001’}
hbase(main):010:0> scan ‘student’,{STARTROW => ‘1001’}
4.查看錶結構
hbase(main):011:0> describe ‘student’
5.更新指定字段的數據
hbase(main):012:0> put ‘student’,‘1001’,‘info:name’,‘Nick’
hbase(main):013:0> put ‘student’,‘1001’,‘info:age’,‘100’
6.查看“指定行”或“指定列族:列”的數據
hbase(main):014:0> get ‘student’,‘1001’
hbase(main):015:0> get ‘student’,‘1001’,‘info:name’
7.統計表數據行數
hbase(main):021:0> count ‘student’
8.刪除數據
刪除某rowkey的全部數據:
hbase(main):016:0> deleteall ‘student’,‘1001’
刪除某rowkey的某一列數據:
hbase(main):017:0> delete ‘student’,‘1002’,‘info:sex’
9.清空表數據
hbase(main):018:0> truncate ‘student’
提示:清空表的操作順序爲先disable,然後再truncate。
10.刪除表
首先需要先讓該表爲disable狀態:
hbase(main):019:0> disable ‘student’
然後才能drop這個表:
hbase(main):020:0> drop ‘student’
提示:如果直接drop表,會報錯:ERROR: Table student is enabled. Disable it first.
11.變更表信息
將info列族中的數據存放3個版本:
hbase(main):022:0> alter ‘student’,{NAME=>‘info’,VERSIONS=>3}
hbase(main):022:0> get ‘student’,‘1001’,{COLUMN=>‘info:name’,VERSIONS=>3}
3、Hbase的架構
3.1 邏輯結構
上圖是用常見的二維表格在hbase中存儲的邏輯結構
每一行的數據是按照rowKey來查找的,其中,因爲該表可能列多,行多,所以我們
把多個列按照列族來管理,一個列族中包括多個列
把多個行按照Region來管理,一個Region中包括多行數據
把一個Region中的一個列族的數據叫做Store
3.2 物理存儲結構
上面說的是邏輯結構,那麼它實際上是如何存儲數據的
注意:在Hbase中增刪改數據,都會增加數據。只不過是type的不同
上圖體現的是一行數據是怎麼在Hbase中進行存儲的
在關係庫中,一個人的各種信息數據是以一行數據進行存儲的,但在Hbase中並不是按照一行來存儲的。而是把每個列的值都存爲1行,關鍵信息爲RowKey,列族信息,列名,時間戳,操作類型(添加這條數據時是刪除還是添加還是修改),值
-
ROW:HBase表中的每行數據都由一個RowKey和多個Column(列)組成,數據是按照RowKey的字典順序存儲的,並且查詢數據時只能根據RowKey進行檢索,所以RowKey的設計十分重要。
-
Column:HBase中的每個列都由Column Family(列族)和Column Qualifier(列限定符)進行限定,例如info:name,info:age。建表時,只需指明列族,而列限定符無需預先定義。
-
Time Stamp:用於標識數據的不同版本(version),每條數據寫入時,如果不指定時間戳,系統會自動爲其加上該字段,其值爲寫入HBase的時間。
-
Cell:由{rowkey, column Family:column Qualifier, time Stamp} 唯一確定的單元。
cell中的數據是沒有類型的,全部是字節碼形式存貯。
-
Name Space:命名空間,類似於關係型數據庫的DatabBase概念,每個命名空間下有多個表。HBase有兩個自帶的命名空間,分別是“hbase”和“default”,“hbase”中存放的是HBase內置的表,“default”表是用戶默認使用的命名空間。
-
Region:表的切片。類似於關係型數據庫的表概念。不同的是,HBase定義表時只需要聲明列族即可,不需要聲明具體的列。這意味着,往HBase寫入數據時,字段可以動態、按需指定。因此,和關係型數據庫相比,HBase能夠輕鬆應對字段變更的場景。
3.3 架構原理
首先數據的存儲依賴於HDFS,爲HBase提供最終的底層數據存儲服務,同時爲HBase提供高可用的支持。
在Hbase的框架中,HMaster依賴於ZK,HMaster的作用管理數據的元數據(Hbase有一個meta表),類似於Hadoop中的NameNode
這裏假設:Hbase集羣有2個節點進行數據存儲
-
每個節點都會有個進程HRegion Server,由Master進行管理,負載均衡。
-
而HRegion Server爲Region的管理者,也就是其中包含着多個Region
-
Region是表的切片,所以Region中又有多個Store(列族的切片),也就是說同一個Region中的不同的Store來自於不同的列族
-
在每個Store中,數據的存儲又依賴於內存區域:Mem Store,當內存達到一定的條件,就會刷寫到磁盤(刷寫機制見3.6),多次刷寫後就有了多個Store File,刷寫到磁盤的文件格式爲HFile
-
考慮到多個刷寫出來的文件較多,所以進行合併,當合並後的文件過大的時候(默認達到10G切分),不便於查找,按照midRowKey將進行切分。
-
最後Store File真正的存儲還是要依賴於HDFS,其中還有Hlog也存儲在HDFS(Hlog爲預寫入日誌,及時落盤,用於HBase恢復數據)
-
HMaster和HDFS進行通信,來向HMaster彙報存儲數據的元數據
術語解釋:
1)Region Server
Region Server爲Region的管理者,其實現類爲HRegionServer,主要作用如下:
對於數據的操作:get, put, delete;
對於Region的操作:splitRegion、compactRegion。
2)Master
Master是所有Region Server的管理者,其實現類爲HMaster,主要作用如下:
對於表的操作:create, delete, alter
對於RegionServer的操作:分配regions到每個RegionServer,監控每個RegionServer的狀態,負載均衡和故障轉移。
3)Zookeeper
HBase通過Zookeeper來做Master的高可用、RegionServer的監控、元數據的入口以及集羣配置的維護等工作。
3.4 Hbase的寫流程
1)客戶端Client先訪問zookeeper,獲取hbase:meta表位於哪個RegionServer。
2)客戶端繼續訪問對應的RegionServer,獲取hbase:meta表,根據讀請求的namespace:table/rowkey,查詢出要寫入的目標數據位於哪個RegionServer中的哪個Region中。並將該table的region信息以及meta表的位置信息緩存在客戶端的meta cache(LRUcache方法,最近最常使用),方便下次訪問。
3)客戶端Client與目標RegionServer建立連接;
4)將數據順序寫入(追加)到WAL(也就是Hlog);
5)將數據寫入對應的MemStore,數據會在MemStore進行排序;
6)向客戶端發送ack;這個時候及時數據沒有落盤,用戶也可以查到。假如這個時候機器掛掉了,WAL也能幫助恢復
7)等達到MemStore的刷寫時機後,將數據刷寫到HFile。
3.5 讀流程
數據的讀操作與HMaster沒有關係
1)1-3步通寫流程
4)分別在Block Cache(讀緩存),MemStore和Store File(HFile)中查詢目標數據,並將查到的所有數據進行合併。此處所有數據是指同一條數據的不同版本(time stamp)或者不同的類型(Put/Delete)。
這裏的查詢過程:
先要同時讀取Block Cache(讀緩存)和MemStore,再檢索新落盤的文件,其中Block Cache緩存的是上一次落盤的文件
比如:同一個RowKey先寫入(張三,時間戳爲78),查找後緩存到Block Cache,過了幾個小時,它已經落盤爲文件,後寫入(李四,時間戳爲89),也落盤爲文件了,但沒進行查找,最後又寫入(王五,時間戳爲66),還在內存中
這個時候如果我們查找,理論上需要返回的是時間戳大的李四
查找過程:檢索內存,時間戳爲66,Block Cache緩存的是時間戳爲78的張三,而李四屬於是新落盤的文件,所以這個時候必須內存、緩存和文件都進行讀取,才能返回結果。
5) 將從文件中查詢到的數據塊(Block,HFile數據存儲單元,默認大小爲64KB)緩存到Block Cache。
6)將合併後的最終結果返回給客戶端
3.6 刷寫機制
1.當單個Region中的memstroe的總大小達到了(默認值128M),其所在region的所有memstore都會刷寫。
參數:hbase.hregion.memstore.flush.size(默認值128M)
2.當Region Server中memstore的總大小達到JVM堆內存的0.4時,region會按照其所有memstore的大小順序(由大到小)依次進行刷寫。這個時候會阻塞客戶端的寫操作,直到當前內存的數據量小於堆內存的0.4*0.95,也就是堆內存的0.38時,纔會打開寫操作。
原因:只有當一直髮生寫操作,memstore的總大小達到JVM堆內存的0.4,那麼這個時候開始了刷寫,但如果說開始刷寫後數據量還能達到JVM堆內存的0.38時,說明寫數據的速度比刷寫的速度快,如果不阻塞寫操作,容易把內存爆了,發生OOM。
參數:java**_**heapsize * hbase.regionserver.global.memstore.size(默認值0.4)
hbase.regionserver.global.memstore.size.lower.limit**(默認值0.95)
3.單個MemStore到達自動刷寫的時間(默認1小時,距離最後操作時間1小時),也會觸發memstore flush。
參數:hbase.regionserver.optionalcacheflushinterval(默認1小時)。
4.當WAL(也就是Hlog)文件的數量超過(默認值32),region會按照時間順序依次進行刷寫,直到WAL文件數量減小到hbase.regionserver.max.log以下(該屬性名已經廢棄,現無需手動設置,最大值爲32)。
3.7 StoreFile合併
由於memstore每次刷寫都會生成一個新的HFile,且同一個字段的不同版本(timestamp)和不同類型(Put/Delete)有可能會分佈在不同的HFile中,因此查詢時需要遍歷所有的HFile。爲了減少HFile的個數,以及清理掉過期和刪除的數據,會進行StoreFile Compaction。Compaction分爲兩種:
- Minor Compaction:會將臨近的若干個較小的HFile合併成一個較大的HFile,但不會清理過期和刪除的數據,可能原來有10個文件,合併完後還有3個。
- Major Compaction:會將一個Store下的所有的HFile合併成一個大HFile,並且會清理掉過期和刪除的數據。合併完後一定是隻有1個文件。(默認爲當一個Store下達到3個文件就會觸發合併,當一個Store下文件數達到10時就會暫緩刷寫,因爲這個時候刷寫的速度大於合併的速度)
3.7 Region Split
默認情況下,每個Table起初只有一個Region,隨着數據的不斷寫入,Region會自動進行拆分。剛拆分時,兩個子Region都位於當前的Region Server,但處於負載均衡的考慮,HMaster有可能會將某個Region轉移給其他的Region Server。
Region Split時機:
1.當1個region中的某個Store下所有StoreFile的總大小超過hbase.hregion.max.filesize(默認爲10G),該Region就會進行拆分(0.94版本之前)。
2.當1個region中的某個Store下所有StoreFile的總大小超過
Min(R^2 * “hbase.hregion.memstore.flush.size”,hbase.hregion.max.filesize"),該Region就會進行拆分,其中R爲當前Region Server中屬於該Table的個數(0.94版本之後)
4、Hbase的API
未完待續。。。
5、Hbase的優化
未完待續。。。
好了,關於Hbase的基本介紹就到這裏了,知識水平、經驗有限,可能有些細節沒講明白,歡迎大家指正。歡迎大家點贊、轉發、評論哈。