最近重新回到熟悉的hbase领域,感慨还是很多。首先终于又可以沉下心来好好搞技术了,其次看到现在有冲劲有追求的年轻人就像看到原来的自己。大数据需要一代一代人传承下去。
最近处于集群管理方便以及资源合理利用的考虑我们上线了region group的patch,将原来在2.0里面才合并的patch 加到了0.98版本中。初始使用的时候挺好,但是也遇到了一点问题——在做表group之间迁移的时候发现master页面上的元数据信息有误。而实际的region分配却没问题
为啥会出现这种情况,就需要我们了解hbase关于表、region元数据如何管理的问题。
首先,大家知道的比较多的是zk中存储的元数据信息
一、ZK元数据
第一级目录/hbase
第二级子目录
/meta-region-server ## meta表所在的rs位置,最初的bigtable论文中是有root表到meta表两级的,hbase原来也有,后来是发现一个meta表能索引的region数量已经足够用了,而多加一级root表多一次路由没意义就舍弃掉了
/acl ## 子节点存储表以及namespace级别权限控制,再下一级子节点存储哪些user拥有什么权限
/backup-masters ## 子节点存储standby master的地址,端口,启动时间
/table ## 子节点存储这个集群所有的表信息,无论是否enable
/draining ## 存储regionserver的临时变化情况,一般是下线多个regionserver时使用
/region-in-transition ## 存储处于事物中的region(split/online/offline/compact等)
/running ## hbase集群是否正常运行
/table-lock ## 锁表信息,在表发生变更时使用
/master ## 集群的master地址
/balancer ## loaderbalancer是否被开启
/namespace ## 当前所有的namespace
/hbaseid ## 集群启动时生成的唯一id
/online-snapshot ## 在线的快照
/replication ## hbase的replication配置,有rs和peers两个元数据信息
/groupInfo ## 存储的group信息
/splitWAL ## 用来构造一个region server的splitlog目录
/recovering-regions ## 存储恢复中的regions
/rs ## 当前所有在线的regionserver信息
二、meta表元数据
meta表中存储的就是所有region状态的信息
rowkey组成为——namespace:tablename,,timestamp.md5
列族为info,子列包括
server——region所属regionserver位置
serverstartcode——server启动的startcode,rs每次重启之后就不是"自己"了,而是用startcode标识的一个rs,所以要重新分配region
regioninfo——region的ENCODED, STARTKEY, ENDKEY
三、HDFS目录中元数据
/hbase/.tmp ## 临时目录,一般是存放compact、split等操作过程中的临时文件
/hbase/WALs ## 存储每个regionserver的WAL日志,子目录是每个rs的名称
/hbase/archive ## 存储compact过程中不用的HFile,删除表的数据也再,过期(5分钟)会被删除.可以用来恢复误drop的表,快照也存储在这
/hbase/corrupt ## 错误文件路径
/hbase/data ## 所有的表数据都在data下
/hbase/hbase.id ## 当前集群启动的id,每次启动都不同
/hbase/hbase.version ## hbase版本号
/hbase/oldWALs ## 过期的WAL日志,等待被清除
四、Hmaster内存中的数据
这个部分的数据在任何地方都比较少介绍,但是其实是非常重要的!
infoServer——存储web UI需要的相关信息
ZookeeperWatcher——保持和zooKeeper连接
activeMasterManager——管理并存储了当前active的master
regionServerTracker——追踪regionserver
drainingServerTracker——追踪drainning状态regionserver
groupAdminServer——region group元数据信息
tableNamespaceManager——namespace元数据信息
五、HBck检查过程
有了上面所说的元数据,大家可以注意到,同样的一份数据在hbase中分别存储在了4个不同的地方,数据就存在不一致的可能。那我们就从Hbase自带的hbck角度来看看什么样的情况会被hbase认为是元数据异常,又是如何去做修复的?
这里只分析核心检查的部分,其余检查准备阶段略过
// do the real work of hbck
connect();
try {
// if corrupt file mode is on, first fix them since they may be opened later
if (checkCorruptHFiles || sidelineCorruptHFiles) {
LOG.info("Checking all hfiles for corruption");
HFileCorruptionChecker hfcc = createHFileCorruptionChecker(sidelineCorruptHFiles);
setHFileCorruptionChecker(hfcc); // so we can get result
Collection tables = getIncludedTables();
Collection tableDirs = new ArrayList();
Path rootdir = FSUtils.getRootDir(getConf());
if (tables.size() > 0) {
for (TableName t : tables) {
tableDirs.add(FSUtils.getTableDir(rootdir, t));
}
} else {
tableDirs = FSUtils.getTableDirs(FSUtils.getCurrentFileSystem(getConf()), rootdir);
}
hfcc.checkTables(tableDirs);
hfcc.report(errors);
}
//到这一步先检查HFile的数据格式是否正确,作为第一步做的检查
// check and fix table integrity, region consistency.
int code = onlineHbck();
//这里调用了onlineHbck做线上检查使用
setRetCode(code);
// If we have changed the HBase state it is better to run hbck again
// to see if we haven't broken something else in the process.
// We run it only once more because otherwise we can easily fall into
// an infinite loop.
if (shouldRerun()) {
try {
LOG.info("Sleeping " + sleepBeforeRerun + "ms before re-checking after fix...");
Thread.sleep(sleepBeforeRerun);
} catch (InterruptedException ie) {
return this;
}
// Just report
setFixAssignments(false);
setFixMeta(false);
setFixHdfsHoles(false);
setFixHdfsOverlaps(false);
setFixVersionFile(false);
setFixTableOrphans(false);
errors.resetErrors();
code = onlineHbck();
setRetCode(code);
}
} finally {
IOUtils.cleanup(null, connection, meta, admin);
}
return this;
---------------------------------------------------------------------------------------------------------
/**
* Contacts the master and prints out cluster-wide information
* @return 0 on success, non-zero on failure
*/
public int onlineHbck() throws IOException, KeeperException, InterruptedException, ServiceException {
// print hbase server version
errors.print("Version: " + status.getHBaseVersion());
offlineHdfsIntegrityRepair();
//这里是对HBase表在hdfs路径上的存储路径进行检查,是否符合标准
// turn the balancer off
boolean oldBalancer = admin.setBalancerRunning(false, true);
try {
onlineConsistencyRepair();
}
finally {
admin.setBalancerRunning(oldBalancer, false);
}
if (checkRegionBoundaries) {
checkRegionBoundaries();
}
offlineReferenceFileRepair();
checkAndFixTableLocks();
// Check (and fix if requested) orphaned table ZNodes
checkAndFixOrphanedTableZNodes();
// Remove the hbck lock
unlockHbck();
// Print table summary
printTableSummary(tablesInfo);
return errors.summarize();
}
--------------------------------------checkAndFixConsistency();-------------------------