<div class="blogpost-body" id="cnblogs_post_body" style="font-size: 16px;">
<div>
<p>客户端在进行put、delete、get等操作的时候,它都需要数据到底存在哪个Region Server上面,这个定位的操作是通过</p>
<p>Connection.locateRegion方法来完成的。</p>
<div class="cnblogs_code">
<pre class="blockcode"><code class="blockcode">loc = hConnection.locateRegion(this.tableName, row.getRow());</code></pre>
</div>
<p> 这里我们首先要讲hbase的两张元数据 <font color="#ff0000">表-ROOT-和.META. </font>表,它们一个保存着 <font color="#ff0000">region的分部信息</font>,一个保存着<font color="#ff0000">region</font>的详细信息。在《hbase实战》这本书里面详细写了查找过程总共有8步:</p>
<p> (1)<font color="#0000ff">客户端-》zk </font>-(ROOT-表在哪)</p>
<p> (2)<font color="#0000ff">zk->客户端</font><font color="#ff0000">(-ROOT-</font>在<font color="#ffd700">RegionServer X node</font>中)</p>
<p> (3)客户端-><font color="#ffd700">x RegionServer</font> 发起查询,-> 去那个<font color="#3cb371">META</font>表可以查到T1表里的 YYYY rowkey</p>
<p> (4)<font color="#ff0000">x RegionServer</font> -ROOT-> 客户端 (<font color="#ff00ff">RegionServer</font><font color="#ff00ff">在 X1</font> 上的<font color="#ff00ff">.META</font>.<font color="#ff00ff"> region </font>的 M2可以找到</p>
<p> (5)客户端-》<font color="#ff00ff">RegionServer </font> X1 上的.<font color="#ff00ff">META. region</font> <font color="#ff00ff">M2</font>查询T1表的YYYY key行数据在哪个region上,哪一个Region Server可以提供服务</p>
<p> (6)<font color="#ff00ff">RegionServer </font> X1 告诉客户端,在<font color="#ff00ff">RegionServer </font> X1 上面的<font color="#993366">region RG33</font></p>
<p> (7)客户端向<font color="#ff00ff">RegionServer </font> X1上面的region RG33 发起请求,我要读取00009行</p>
<p> (8)<font color="#ff00ff">RegionServer </font> X1 的 region RG33 把数据发给客户端;</p>
<p> 代码里面查看 HConnectionManager.locateRegion() 的实现过程</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar">
<span class="cnblogs_code_copy"><a href="" title="复制代码">
<div style="text-align: center;">
<img alt="复制代码" name="" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-f68093ba3cfd6ad167688429d8f82364.gif" style="outline: none;">
</div></a></span>
</div>
<pre class="blockcode"><code class="blockcode">private HRegionLocation locateRegion(final TableName tableName,
final byte [] row, boolean useCache, boolean retry) {
if (tableName.equals(TableName.META_TABLE_NAME)) {
return this.registry.getMetaRegionLocation();
} else {
// Region not in the cache - have to go to the meta RS </code></pre>
<pre class="blockcode"><code class="blockcode"> return locateRegionInMeta(TableName.META_TABLE_NAME, tableName, row,</code></pre>
<pre class="blockcode"><code class="blockcode"> useCache, userRegionLock, retry);
}
}</code></pre>
<div class="cnblogs_code_toolbar">
<span class="cnblogs_code_copy"><a href="" title="复制代码">
<div style="text-align: center;">
<img alt="复制代码" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-f68093ba3cfd6ad167688429d8f82364.gif" style="outline: none;">
</div></a></span>
</div>
</div>
<p> <font color="#0000ff">TableName.META_TABLE_NAME,这个就是我们要找的-ROOT</font>-,在0.96里面它已经被取消了,<font color="#0000ff">取而代之的是META表中的第一个regionHRegionInfo.FIRST_META_REGIONINFO,它位置在zk的meta-region-server节点</font>当中的。</p>
<p> 好吧,再回到代码里面,我们这里肯定是走else这个路径,我们进入locateRegionInMeta看看。</p>
<p>代码好长啊,我们一点一点看吧,先从缓存里面找,把tableName和rowkey传进去。</p>
<div class="cnblogs_code">
<pre class="blockcode"><code class="blockcode">if (useCache) {
location = getCachedLocation(tableName, row);
if (location != null) {
return location;
}
}</code></pre>
</div>
<p> 这里的cache是这样组织的Map<tableName, SoftValueSortedMap<rowkey, HRegionLocation>>, 通过tableName获得它的基于rowkey的子map,这个map是按照key排好序的,如果找不到合适的key,就找比它稍微小一点的key。</p>
<p> 接下来就是一个for循环了,默认是尝试31次</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar">
<span class="cnblogs_code_copy"><a href="" title="复制代码">
<div style="text-align: center;">
<img alt="复制代码" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-ccc6fd7d1dfd3456d4a65bac245c6264.gif" style="outline: none;">
</div></a></span>
</div>
<pre class="blockcode"><code class="blockcode"> HRegionLocation metaLocation = null;
try {
// locate the meta region 还好这个不是玩递归,直接获取meta表所在的位置
metaLocat |
|