HBase异常——当RegionServer Crash之后

本文深入解析了HBase中RegionServer崩溃后的恢复机制,从崩溃检测、节点更新、任务分配到HLog恢复和Region加载等关键步骤,详细阐述了故障后系统如何确保数据的一致性和可用性。

真是一篇好文章啊,条例清楚,看过这篇文章再去看看代码(推荐阅读http://www.spnguru.com里面关于hbase的文章,很赞!)。

对于分布式数据库来说,容错处理是非常重要的一个部分。RegionServer是HBase系统中存在最多的节点,所以对于RegionServer的容错处理对于HBase来说至关重要。本文对RegionServer的容错处理进行Step by Step的分析,希望能解释清除整个过程并加以点评。

我们假设在HBase运行的过程中有一个RegionServer突然Crash, 基于这个场景进行分析。

1. RegionServer Crash了

Crash的原因可能有很多种,程序自身挂掉,OS挂掉,网络断掉,电源断掉,等等。但从MasterServer的角度看来只有一种现象,那就是RegionServer在Zookeeper上面注册的Node消失了。我们知道当RegionServer启动的时候会产生一个StartCode,并在Zookeeper上面注册一个EPHEMERAL类型的节点。

一旦RS和ZK之间的通信消失,EPHEMERAL的节点就会被自动删除。而MasterServer则会捕获这个Node消失的事件。

捕获这个事件之后,所有的事情就交给ServerManager.expireServer()来处理了。

2. ServerManager处理

首先ServerManager会更新自己的列表,包括deadserver list, online server list 以及 server connection list. 当然在我们试图Stop整个Cluster的时候也会收到同样的请求,不予理睬就好了。

并不是所有的RS Crash都做相同的处理,有些RS比较特殊,他们正在管理-ROOT-表或者.META.表。如果我们重新分配Region, 就需要修改.META.表,如果要访问.META.表先要查询-ROOT-表 (参见以前的文章,client如何路由到正确的RS)。问题是现在管理-ROOT-表或者.META.表的RS挂了,显然第一要务是让-ROOT-和.META.有所归属,能够正常的对他们进行读写。

接下来ServerManager通过传递Event的方式将任务交给Excutor线程来处理,具体调用MetaServerShutdownHandler或者ServerShutdownHandler的process函数。

3. ServerShutdownHandler处理

MetaServerShutdownHandler是继承于ServerShutdownHandler的,除了打上META的标志以外其他都一样,所以我们只介绍ServerShutdownHandler的处理。

处理的第一步是Split HLog。当RS Crash的时候所有MemCache里面的内容都会被丢掉,这些内容还没有来得及Flush到HFile里面。感谢WAL机制,所有的内容都可以在HLog File里面找到。问题是原来管理这些HLog文件的RS已经挂掉了,需要将这些HLog交给新的RS去处理。往往这些HLog不会交给同一个新的RS去处理,因为HLog可能包含多个Region的内容,而这些Region可能会分配给不同的RS。这样看来最好的方式是让HLog里面的每一个Entry跟随Region,Region被分配给哪个RS,就让那个RS来处理这个Entry。事实上MasterServer也确实是这么做的。具体步骤如下:

1) 从Crash的RS的HLog目录下读取每个HLog文件

2) 根据文件中每个Entry所隶属的Region找到Region文件的存储目录。将Entry写到一个叫做 “recovered.edits” 的文件夹中。Entry写入的格式依然是HLog的格式。

3) 将Region分配给某个具体的RS,剩下的任务由RS处理

4. Assign RegionServer

前面有提到过,如果Crash的RS正在Handle -ROOT-或者.META.,需要特殊处理。特殊处理的方式就是先assign -ROOT-和.META.,并等待他们online。这样可以保证后需的assign工作。

具体Assign的过程可以单独用一章来讲,这里不做详细介绍。

5. RegionServer加载新的Region

一旦某个RS被assign了一个新的Region, 它就会试图加载这个新Region. 在加载的过程中RS会查看 “recovered.edits” 目录,试图从HLog中恢复丢失的数据。具体过程如下:

1) 扫描目录中的每个HLog文件

2) 跳过那些Sequence ID小于Region MAX Seq ID的Entry,因为这些Entry已经在HFile里面了。

3) 找到丢失的Entry并写入MemStore

4) Flush MemStore到HFile

5) 删除目录下的文件

具体可以参考 HRegion.replayRecoveredEdits

6. 分析后的思考

写到这里整个过程已经基本上结束了,但除了分析过程,还有许多我们可以思考的地方。

1) 恢复一个RegionServer需要多少时间?

等待ZK Node消失 + Split Log + Assign Region + Recover HLog +Region Online

这是从正常情况看来需要花费的时间,Log越多,Region越多,需要花费的时间越长。别忘了如果RS正在Handle -ROOT-或者.META.,需要的时间会更多。

2) RegionServer的问题真的可以都被侦测吗?

如果RS已经停止服务,但依然存活,ZK Node 就不会消失,这种情况应该发生过。目前只能作为Bug去修理。也许额外的Monitor是一个弥补的办法(定期Scan什么的)。

3) 容错性到底有多强?

如果是RS接二连三的挂掉,刚刚分配的RS又挂掉,等等极端情况,HBase的容错性到底有多强呢?也许需要针对性的理论分析和详细测试。

4) MasterServer挂掉?

这个问题在HBase 0.90中有所改善,有兴趣的话可以去看看。


### Java HBase 2.4.5 客户端 RegionServer 异常重试配置 在使用 HBase 的 Java 客户端时,可以通过 `hbase.client.retries.number` 参数来控制客户端在遇到 RegionServer 异常时的重试次数。以下是具体的实现方法以及注意事项。 #### 配置说明 `hbase.client.retries.number` 是用于定义当客户端尝试连接到某个不可用的 RegionServer 或其他服务失败时的最大重试次数[^1]。默认情况下,该值通常被设置为较大的数值(如 35),但在实际应用中可以根据需求进行调整。 为了模拟 RegionServer 异常并验证重试机制的效果,可以手动修改 `hbase-site.xml` 文件中的某些配置项,例如禁用特定编码器或减少可用处理器数量,从而触发异常场景[^1]。 #### 示例代码 以下是一个完整的示例程序,展示如何通过 Java API 设置 `hbase.client.retries.number` 并测试其行为: ```java import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.Table; public class HBaseRetryExample { public static void main(String[] args) throws Exception { // 创建 HBase 配置对象 Configuration config = HBaseConfiguration.create(); // 调整重试次数参数 config.setInt("hbase.client.retries.number", 5); // 将最大重试次数设为 5 try (Connection connection = ConnectionFactory.createConnection(config)) { TableName tableName = TableName.valueOf("test_table"); try (Table table = connection.getTable(tableName)) { Get get = new Get("row_key".getBytes()); // 执行获取操作 System.out.println(table.get(get)); } catch (Exception e) { System.err.println("Error occurred while accessing the table: " + e.getMessage()); } } } } ``` 在此代码片段中: - 使用 `config.setInt("hbase.client.retries.number", 5)` 来显式指定客户端的最大重试次数为 5 次。 - 如果目标表所在的 RegionServer 不可访问,则客户端会在达到设定的重试上限之前不断尝试重新建立连接[^2]。 #### 注意事项 除了调整 `hbase.client.retries.number` 外,还可以考虑优化其他相关参数以提高系统的稳定性和性能。例如: - **线程池大小**:通过调节 `hbase.regionserver.handler.count` 可以影响服务器端对请求的响应效率[^4]。 - **垃圾回收调优**:对于大规模生产环境下的内存管理问题,建议启用 CMS 垃圾收集器并通过 `export HBASE_OPTS` 添加必要的 GC 日志选项[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值