日期:2014-05-16 浏览次数:20642 次
?0.90.X的get和scan操作原理上是比较一致的,get操作都变为scan操作。不过在分析之前我们还是从get说起
话不多说首先看看get这个接口,hbase客户端对于get有以下几种:
public Get(byte [] row)
public Get(byte [] row, RowLock rowLock)
?其中rowlock主要是用来保证行的事务性,即每个get是以一个row来标记的一个row中可以有很多family和column
get还有很多函数如addfamily,addcolumn,这里我主要以指定row family column来get数据
?
ok我们来看HTable的get操作
public Result get(final Get get) throws IOException { return connection.getRegionServerWithRetries( new ServerCallable<Result>(connection, tableName, get.getRow()) { public Result call() throws IOException { return server.get(location.getRegionInfo().getRegionName(), get); } } ); }
?这也是一个RPC调用的过程且其返回结果为Result。
1.调用HConnectManger的getRegionServerWithRetries(ServerCallable<T> callable)
callable.instantiateServer(tries != 0);
????????? return callable.call();
这两步主要是找到该get的row所在的region,locateRegion
这个过程以后再来分析,总之就是找到该get所在的region,并与该region所在server通信
我们主要来看RegionServer端的Get操作,主要是region的get操作
?
List<KeyValue> result = get(get);
private List<KeyValue> get(final Get get) throws IOException { Scan scan = new Scan(get); List<KeyValue> results = new ArrayList<KeyValue>(); InternalScanner scanner = null; try { scanner = getScanner(scan); scanner.next(results); } finally { if (scanner != null) scanner.close(); } return results; }
?上述这个过程就是region的get过程,我们用下图来进行一个简单的描述
?
每个region中有一个regionscanner,每个regionscanner中维持一个heap的优先级队列,其中包含所有的storescanner,每个storescanner中包含一个Memstorescanner和n个Hfilescanner
进行查找时首先会定位到hfilestore或是memstore,找到这个get的row起始位置
?
在HFile或是memstore中数据视安从小到大进行排序的,排序规则是按keyvalue的大小,row,family,column,timestamp,最后是type。
?
?
上图就是模拟hfile里面keyvalue的一个排序规则。
哪些get的话如果没有指定时间戳的话会返回最近的一个值。,get也可以制定取回的版本数。
如果我们需要取回3个版本如上图所示
首先每个Hfile会定位到该row的起始处位置如此处在这3个Hflie的开头,若指定的column是C1
然后比较这三个文件开头的keyvalue大小,显然第三个R1,cf,c1,9最小,故首先取它
然后该文件指针往下移,重新比较当前指针的最小值,此时第一个文件的R1,cf,c1,8最小故第二个版本取它
然后指针下移继续比较知道满足版本数为止