一、为什么需要定位
hbase是一个主从的master/slave架构,默认使用zk的选举来支持HMaster的高可用实通过监听临时节点,使用类似分布式锁的方法来争抢创建节点后成为新的master。
一个HMaster通常会对应多个HRegionServer,而每一个HRegionServer又可以有多个HRegion,需要注意的是,我们的Table数据刚开始的时候只会存在于一个HRegion里面,但是随着表数据量的增大,会发生spilter操作,然后table数据很可能会存在不同HRegionServer的HRgion里面,而每个HRegion存的是某张表的一部分连续的数据。当我们拿着一个tableName,Rowkey去hbase上查数据的时候,它是怎么定位到是哪一个HRegion里存着这个rowkey对应的数据呢,下面我们以单个rowkey的get操作为例来看一下源码实现(其它操作如scan等在找Region部分的源码实现也是一样)。
二、如何定位
先看一段简单的单元测试
@Test
public void readFromHbase() throws IOException{
HBaseSource hbaseSource = HBaseSource.getHbaseSource(appName);
hbaseSource.openConnection();
Result rs = hbaseSource.searchDataByGet("TABLE", "TTTTT1201701011200222");
for(KeyValue kv : rs.raw()){
System.out.println("row:" + new String(kv.getRow()));
System.out.println("qualifier-value:" + new String(kv.getQualifier()) +";" + new String(kv.getValue()));
}
}
这里面的searchDataByGet返给就是通过tableName,rowkey去查询数据,下面我们就来分析如何根据这2个调节去获取数据
2.1 首先在初始化Table实例的时候,有一个地方需要注意
private void finishSetup() throws IOException {
if (connConfiguration == null) {
connConfiguration = new ConnectionConfiguration(configuration);
}
this.operationTimeout = tableName.isSystemTable() ?
connConfiguration.getMetaOperationTimeout() : connConfiguration.getOperationTimeout();
this.rpcTimeout = configuration.getInt(HConstants.HBASE_RPC_TIMEOUT_KEY,
HConstants.DEFAULT_HBASE_RPC_TIMEOUT);
this.scannerCaching = connConfiguration.getScannerCaching();
this.scannerMaxResultSize = connConfiguration.getScannerMaxResultSize();
if (this.rpcCallerFactory == null) {
this.rpcCallerFactory = connection.getNewRpcRetryingCallerFactory(configuration);
}
if (this.rpcControllerFactory == null) {
this.rpcControllerFactory = RpcControllerFactory.instantiate(configuration);
}
// puts need to track errors globally due to how the APIs currently work.
multiAp = this.connection.getAsyncProcess();
this.closed = false;
this.locator = new HRegionLocator(tableName, connection);
}
构造函数初始化HRegionLocator对象,conection可用理解为一个集群连接器
, row): locateRegion(tableName, row); }
public HRegionLocator(TableName tableName, ClusterConnection connection) {
this.connection = connection;
this.tableName = tableName;
}
2.2 执行get操作
代码里的get会调用Htable里的下面的方法
@Override
public Result get(final Get get) throws IOException {
return get(get, get.isCheckExistenceOnly());
}
接着调用
private Result get(Get get, final boolean checkExistenceOnly) throws IOException {
// if we are changing settings to the get, clone it.
if (get.isCheckExistenceOnly() != checkExistenceOnly || get.getConsistency() == null) {
get = ReflectionUtils.newInstance(get.getClass(), get);
get.setCheckExistenceOnly(checkExistenceOnly);
if (get.getConsistency() == nul