HBase——Replication(复制)实践

 

前言

Replication:复制,指的是持续的将同一份数据拷贝到多个地方进行存储,是各种存储系统中常见而又重要的一个概念,

可以指数据库中主库和从库的复制,也可以指分布式集群中多个集群之间的复制,还可以指分布式系统中多个副本之间的复制。

它的难点在于数据通常是不断变化的,需要持续的将变化也反映到多个数据拷贝上,并保证这些拷贝是完全一致的。

通常来说,数据复制到多个拷贝上有如下好处:

  • 多个备份提高了数据的可靠性

  • 通过主从数据库/主备集群之间的复制,来分离OLTP和OLAP请求

  • 提高可用性,即使在单副本挂掉的情况下,依然可以有其他副本来提供读写服务

  • 可扩展,通过增加副本来服务更多的读写请求

  • 跨地域数据中心之间的复制,Client通过读写最近的数据中心来降低请求延迟

HBase中的Replication指的是主备集群间的复制,用于将主集群的写入记录复制到备集群。HBase目前共支持3种Replication:

  • 异步Replication
  • 串行Replication
  • 同步Replication

此篇文章介绍的是:第一种,异步Replication。

 

一、原理

首先看下官方的一张图:

HBase——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 Replication步骤:

  1. HBase Client向Master写入数据
  2. 对应RegionServer写完HLog后返回Client请求
  3. 同时replication线程轮询HLog发现有新的数据,发送给Slave
  4. Slave处理完数据后返回给Master
  5. 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'

HBase——Replication(复制)实践

  • 在Slave备集群,执行以下命令查看是否复制成功:
scan 'tt'

HBase——Replication(复制)实践

  • 在Master主集群,执行以下命令更新tt表数据:
put 'tt','1','cf','aaabbb'
  • 在Slave备集群,执行以下命令查看是否更新成功:
scan 'tt'

HBase——Replication(复制)实践

  • 在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——Replication(复制)实践

数据不一致结果:

HBase——Replication(复制)实践

验证命令说明:

#命令:
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

验证结果参考:

HBase——Replication(复制)实践

 注:只有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。

HBase——Replication(复制)实践

 

  •  Slave上RegionServer异常

对于该种异常HBase处理比较简单,Slave上出现某个RegionServer异常,该RegionServer直接会被标记为异常状态,

后续所有的更新都不会被发送到该台RegionServer,Slave会重新选取一台RegionServer来接收这部分数据。

 

五、相关命令

shell环境为我们提供了很多方法去操作replication特性。

 HBase——Replication(复制)实践

 修改现有表为复制状态:

hbase> disable 'example_table'
hbase> alter 'example_table', {NAME => 'example_family', REPLICATION_SCOPE => '1'}
hbase> enable 'example_table'

 

 

引用:

上一篇:在windows上传一个新的项目到GitHub上


下一篇:【转载】主备环境搭建