前言
Replication:復制,指的是持續的將同一份數據拷貝到多個地方進行存儲,是各種存儲系統中常見而又重要的一個概念,
可以指數據庫中主庫和從庫的復制,也可以指分布式集群中多個集群之間的復制,還可以指分布式系統中多個副本之間的復制。
它的難點在於數據通常是不斷變化的,需要持續的將變化也反映到多個數據拷貝上,並保證這些拷貝是完全一致的。
通常來說,數據復制到多個拷貝上有如下好處:
-
多個備份提高了數據的可靠性
-
通過主從數據庫/主備集群之間的復制,來分離OLTP和OLAP請求
-
提高可用性,即使在單副本掛掉的情況下,依然可以有其他副本來提供讀寫服務
-
可擴展,通過增加副本來服務更多的讀寫請求
-
跨地域數據中心之間的復制,Client通過讀寫最近的數據中心來降低請求延遲
HBase中的Replication指的是主備集群間的復制,用於將主集群的寫入記錄復制到備集群。HBase目前共支持3種Replication:
- 異步Replication
- 串行Replication
- 同步Replication
此篇文章介紹的是:第一種,異步Replication。
一、原理
首先看下官方的一張圖:
需要聲明的是,HBase的replication是以Column Family為單位的,每個Column Family都可以設置是否進行replication。
上圖中,一個Master對應了3個Slave,Master上每個RegionServer都有一份HLog,在開啟Replication的情況下,
每個RegionServer都會開啟一個線程用於讀取該RegionServer上的HLog,並且發送到各個Slave,Zookeeper用於保存當前已經發送的HLog的位置。
Master與Slave之間采用異步通信的方式,保障Master上的性能不會受到Slave的影響。
用Zookeeper保存已經發送HLog的位置,主要考慮在Slave復制過程中如果出現問題后重新建立復制,可以找到上次復制的位置。
HBase Replication步驟:
- HBase Client向Master寫入數據
- 對應RegionServer寫完HLog后返回Client請求
- 同時replication線程輪詢HLog發現有新的數據,發送給Slave
- Slave處理完數據后返回給Master
- Master收到Slave的返回信息,在Zookeeper中標記已經發送到Slave的HLog位置
注:在進行replication時,Master與Slave的配置並不一定相同,比如Master上可以有3台RegionServer,Slave上並不一定是3台,Slave上的RegionServer數量可以不一樣,數據如何分布這個HBase內部會處理。
二、種類
從復制模式上來講,HBase支持主從、主主兩種復制模式,也就是經常說的Master-Slave、Master-Master復制。
- Master-Slave
Master-Slave復制比較簡單,所有在Master集群上寫入的數據都會被同步到Slave上。
- Master-Master
Master-Master復制與Master-Slave類似,主要的不同在於,在Master-Master復制中,兩個Master地位相同,都可以進行讀取和寫入。
配置的時候與Master-Slave模式不同的是,在Master上添加完復制關系后,需要在另外一台Master也添加復制關系,而且兩邊的cluster_id必須相同,
並且在另外一台Master上建表的時候,需要加上列簇的REPLICATION_SCOPE=>’1’配置。
既然Master-Master兩個Master都可以進行寫入,萬一出現一種情況:兩個Master上都進行了對同一表的相同Column Family的同一個rowkey進行寫入,會出現什么情況?
create ‘t’, {NAME=>’cf’, REPLICATION_SCOPE=>’1’} Master1 Master2 put ‘t’, ‘r1’, ‘cf’, ‘aaaaaaaaaaaaaaa’ put ‘t’, ‘r1’, ‘cf’, ‘bbbbbbbbbbbbbbb’
如上操作,Master1上對t的cf列簇寫入rowkey為r1,value為aaaaaaaaaaaaaaa的數據,Master2上同時對t的cf列簇寫入rowkey為r1, value為bbbbbbbbbbbbbbb的數據,
由於是Master-Master復制,Master1和Master2上在寫入數據的同時都會把更新發送給對方,這樣最終的數據就變成了:
Master1 Master2
rowkey value rowkey value
r1 bbbbbbbbbbbbbbb r1 aaaaaaaaaaaaaaaa
從上述表格中可以看到,最終Master1和Master2上cf列簇rowkey為r1的數據兩邊不一致。
所以,在做Master-Master高可用時,確保兩邊寫入的表都是不同的,這樣能防止上述數據不一致問題。
三、配置
1. 准備
需要准備兩個HBase集群來進行試驗,並且需要滿足:
- 集群間版本需要一致
- 集群間服務器需要互通且時間要同步
- 相關表及表結構在兩個集群上存在且相同
2.說明
有些更改不能復制,必須通過其他方法傳播,比如快照或CopyTable。
- 啟用復制之前存在於活動集群中的數據。
- 繞過WAL的操作,例如在使用BulkLoad或writeToWal(false)等API調用時。
- 表模式修改。
3.啟用replication
修改master集群上的hbase-site.xml配置文件,增加以下內容,然后重啟集群。
<property> <name>hbase.replication</name> <value>true</value> <description>打開replication功能</description> </property> <property> <name>replication.source.nb.capacity</name> <value>5000</value> <description>主集群每次像備集群發送的entry最大的個數,推薦5000.</description> </property> <property> <name>replication.source.size.capacity</name> <value>4194304</value> <description>主集群每次像備集群發送的entry的包的最大值大小,不推薦過大</description> </property> <property> <name>replication.source.ratio</name> <value>1</value> <description>主集群里使用slave服務器的百分比</description> </property> <property> <name>hbase.regionserver.wal.enablecompression</name> <value>false</value> <description>主集群關閉hlog的壓縮</description> </property> <property> <name>replication.sleep.before.failover</name> <value>5000</value> <description>主集群在regionserver當機后幾毫秒開始執行failover</description> </property>
4.驗證replication
- 在Master主集群,執行以下命令添加復制關系:
add_peer '100', CLUSTER_KEY => "172.16.10.60:2181:/hbase"
注:上面的是 Slave備集群的zk地址和端口
- 在Master主集群,新建表tt,該表擁有一個列簇名為cf,並且該列簇開啟replication:
create 'tt', {NAME=>'cf', REPLICATION_SCOPE=>'1'}
注:上面REPLICATION_SCOPE的取值范圍為(0,1,2)
- 在Slave備集群,建立相同的表(不支持DDL的復制):
create 'tt', {NAME=>'cf'} #在master-slave模式中,slave不需要開啟復制
- 在Master主集群,執行以下命令往tt表插入一條數據:
put 'tt','1','cf','aaaaa'
- 在Master主集群,執行以下命令查看是否插入成功:
scan 'tt'
- 在Slave備集群,執行以下命令查看是否復制成功:
scan 'tt'
- 在Master主集群,執行以下命令更新tt表數據:
put 'tt','1','cf','aaabbb'
- 在Slave備集群,執行以下命令查看是否更新成功:
scan 'tt'
- 在Master主集群,執行以下命令刪除tt表數據:
put 'tt','1','cf','aaabbb'
- 在Slave備集群,執行以下命令查看是否刪除成功:
scan 'tt'
5.驗證數據
通過HBase自帶的VerifyReplication工具,驗證兩個集群的數據是否一致:
hbase org.apache.hadoop.hbase.mapreduce.replication.VerifyReplication -mappers 10 -bandwidth 1024 1 tt
數據一致結果:
數據不一致結果:
驗證命令說明:
#命令: hbase org.apache.hadoop.hbase.mapreduce.replication.VerifyReplication [--starttime=timestamp1] [--stoptime=timestamp] [--families=comma separated list of families] peerId tableName #命令參考: bash-4.2$ ./bin/hbase org.apache.hadoop.hbase.mapreduce.replication.VerifyReplication Usage: verifyrep [--starttime=X] [--endtime=Y] [--families=A] [--row-prefixes=B] [--delimiter=] [--recomparesleep=] [--batch=] [--verbose] [--sourceSnapshotName=P] [--sourceSnapshotTmpDir=Q] [--peerSnapshotName=R] [--peerSnapshotTmpDir=S] [--peerFSAddress=T] [--peerHBaseRootAddress=U] Options: starttime beginning of the time range without endtime means from starttime to forever endtime end of the time range versions number of cell versions to verify batch batch count for scan, note that result row counts will no longer be actual number of rows when you use this option raw includes raw scan if given in options families comma-separated list of families to copy row-prefixes comma-separated list of row key prefixes to filter on delimiter the delimiter used in display around rowkey recomparesleep milliseconds to sleep before recompare row, default value is 0 which disables the recompare. verbose logs row keys of good rows sourceSnapshotName Source Snapshot Name sourceSnapshotTmpDir Tmp location to restore source table snapshot peerSnapshotName Peer Snapshot Name peerSnapshotTmpDir Tmp location to restore peer table snapshot peerFSAddress Peer cluster Hadoop FS address peerHBaseRootAddress Peer cluster HBase root location Args: peerid Id of the peer used for verification, must match the one given for replication tablename Name of the table to verify Examples: To verify the data replicated from TestTable for a 1 hour window with peer #5 $ hbase org.apache.hadoop.hbase.mapreduce.replication.VerifyReplication --starttime=1265875194289 --endtime=1265878794289 5 TestTable
驗證結果參考:
注:只有GOODROWS時,說明集群間的數據一致;存在BADROWS或ONLY_IN_PEER_TABLE_ROW時,說明集群間的數據不一致。
四、異常情況
HBase復制時,都是通過RegionServer開啟復制線程進行HLog的發送,那么當其中某個RegionServer出現異常時,HBase是如何處理的?
這里需要區別兩種不同的情況,即Master上RegionServer異常和Slave上RegionServer異常。
- Master上RegionServer異常
Master上RegionServer出現異常,由於HLog都是通過RegionServer開啟復制線程進行發送,如果RegionServer出現異常,
這個時候,屬於該台RegionServer的HLog就沒有相關處理線程,這個時候,這部分數據又該如何處理?
Master上某台RegionServer異常,其他RegionServer會對該台RegionServer在zookeeper中的信息嘗試加鎖操作,當然這個操作是互斥的,同一時間只有一台RegionServer能獲取到鎖,
然后,會把HLog信息拷貝到自己的目錄下,這樣就完成了異常RegionServer的HLog信息的轉移,通過新的RegionServer把HLog的信息發送到Slave。
- Slave上RegionServer異常
對於該種異常HBase處理比較簡單,Slave上出現某個RegionServer異常,該RegionServer直接會被標記為異常狀態,
后續所有的更新都不會被發送到該台RegionServer,Slave會重新選取一台RegionServer來接收這部分數據。
五、相關命令
shell環境為我們提供了很多方法去操作replication特性。
修改現有表為復制狀態:
hbase> disable 'example_table' hbase> alter 'example_table', {NAME => 'example_family', REPLICATION_SCOPE => '1'} hbase> enable 'example_table'
引用: