一、环境准备
1、要求两套集群安装相同的CDH版本,如都为CDH4或者CDH5,不限定小版本
2、要求两套集群网络互通,至少保证Master HBase到Salve HBase网络是可达的
二、开启HBase replication功能
启用HBase复制功能,如下图:在修改配置后, 需要重启HBase集群,建议采用滚动重启的方式重启HBase各个实例。
三、配置hosts
在Master集群所有机器的hosts中配置Slave集群的hostname与ip
需要注意的地方有:
1、至少配置slave集群的HBase和zk的hostname
2、hostname必须与slave集群内部使用的hostname一致
四、增加peer
在建立peer前,首先简单的介绍下hbase关于peer的原理以及操作命令,建议参照hbase复制详解。上文介绍得非常的详细,在这里不累述,主要介绍如何正确的关闭一个peer。
首先回顾下创建一个peer的过程:
- 新增一个peer
add_peer 'peerID','zkIp:2181:/hbase'
其中peerID不可与已经存在的peer冲突,可通过list_peers查看已有的peer;
如果配置多个zk:zk1,zk2:2181:/hbase
- 将peerID=1的peer应用表t1
对于已经建立的表,需要开启REPLICATION_SCOPE属性,如:
disable 't1'
alter 't1',{NAME=>"cf", REPLICATION_SCOPE=>"1"}
enable 't1'
对于REPLICATION_SCOPE属性,一开始我一度以为其值=peerID,并且在设置时并未报错。经过查看源码,发现REPLICATION_SCOPE的取值范围为(0,1,2),源码在HConstants类中定义了三种模式:
/**
* 本地模式,当前数据不会被复制
* Scope tag for locally scoped data.
* This data will not be replicated.
*/
public static final int REPLICATION_SCOPE_LOCAL = 0;
/**
* 全局模式,此数据会被复制给所有peer
* Scope tag for globally scoped data.
* This data will be replicated to all peers.
*/
public static final int REPLICATION_SCOPE_GLOBAL = 1;
/**
* 连续模式,数据会按照队列ID的顺序复制给所有的peer
* Scope tag for serially scoped data
* This data will be replicated to all peers by the order of sequence id.
*/
public static final int REPLICATION_SCOPE_SERIAL = 2;
对于0和1这两个取值还比较好理解,而2并不能简单的从上面得到解释
- 将peer应用到表
set_peer_tableCFs 'peerId,'table:cf;table1:cf1,cf2'
append_peer_tableCFs 'peerId,'table:cf;table1:cf1,cf2'
许多的博文里都有提到这两个命令,但是却没有指出两者的区别,这阅读源码(HBase1.2)后,得到这样的解释:
1、append_peer_tableCFs
增加peer到表,粒度到列簇。
2、set_peer_tableCFs
更新tableCFs到peer。假如事先执行了append_peer_tableCFs 'peerId,'table:cf;table1:cf1,cf2',再执行set_peer_tableCFs 'peerId','table1:cf1',那么table1:cf2将从当前peer中移除,而append_peer_tableCFs会保留已有的列簇。两个方式实现的源码如下:
public static UpdateReplicationPeerConfigRequest buildUpdateReplicationPeerConfigRequest(
String peerId, ReplicationPeerConfig peerConfig) {
UpdateReplicationPeerConfigRequest.Builder builder = UpdateReplicationPeerConfigRequest
.newBuilder();
builder.setPeerId(peerId);
builder.setPeerConfig(ReplicationSerDeHelper.convert(peerConfig));
return builder.build();
}
public static void appendTableCFsToReplicationPeerConfig(
Map> tableCfs, ReplicationPeerConfig peerConfig) {
Map> preTableCfs = peerConfig.getTableCFsMap();
if (preTableCfs == null) {
peerConfig.setTableCFsMap(tableCfs);
} else {
for (Map.Entry> entry : tableCfs.entrySet()) {
TableName table = entry.getKey();
Collection appendCfs = entry.getValue();
if (preTableCfs.containsKey(table)) {
List cfs = preTableCfs.get(table);
if (cfs == null || appendCfs == null || appendCfs.isEmpty()) {
preTableCfs.put(table, null);
} else {
Set cfSet = new HashSet(cfs);
cfSet.addAll(appendCfs);
preTableCfs.put(table, Lists.newArrayList(cfSet));
}
} else {
if (appendCfs == null || appendCfs.isEmpty()) {
preTableCfs.put(table, null);
} else {
preTableCfs.put(table, Lists.newArrayList(appendCfs));
}
}
}
}
}
至此,可以验证在Master集群中往表t1写入数据,观察Slave集群是否成功备份。
上面介绍了开启一个表的复制,需要开启REPLICATION_SCOPE属性,然后应用某一个peer,是否会存在这TABLE_CFS和REPLICATION_SCOPE配置有什么区别的疑问?
REPLICATION_SCOPE 是让 replicationSource 开启的 WAL reader 能够看到 log 里哪些 WALEntry 能被 replication , TABLE_CFS 则是在 WALEntry 中过滤出真正需要复制的 cf 数据
五、删除peer
一开始以为删除一个peer的方式很简单,只需运行命令
remove_peer 'peerId'
但是,观察到regionServer日志依旧在尝试连接Slave集群,并且在Master集群的t1表写入数据后,Slave集群依旧同步到了。
一种解决方式为:在remove peer后,将table的REPLICATION_SCOPE属性修改为0。当然,在生产环境对表进行disable也是非常不可取的。
另外一种解决方式:先remove_peer_tableCFs删除表对应的peer信息,再删除peer,一定要记住顺序。最后将表的REPLICATION_SCOPE修改为。修改
我目前并没有测试成功,但是查看社区是有人这么完成了的。就是使用enable_table_replication命令。