往hbase存储图片代码中存大量数据时,代码运行一段时间后出错,求帮助

后使用快捷导航没有帐号?
查看: 6870|回复: 2
hbase在大负载下,不稳定情况分析
金牌会员, 积分 1669, 距离下一级还需 1331 积分
论坛徽章:4
| 文章可以转载,请以超链接形式标明文章原始出处和作者信息网址: 集群在读写过程中,可能由于Region Split或Region Blance等导致Region的短暂下线,此时客户端与HBase集群进行RPC操作时会抛出NotServingRegionException异常,从而导致读写操作失败。这里根据实际项目经验,详细描述这一问题的发现及排查解决过程。1. 发现问题在对HBase集群进行压力测试过程中发现,当实际写入HBase和从HBase查询的量是平时的若干倍时(集群规模10~20台,每秒读写数据量在几十万条记录的量级),导致集群的读写出现一定程度的波动。具体如下:1)写端抛出以下异常信息:org.apache..hbase.client.RetriesExhaustedWithDetailsException: Failed 150 actions: NotServingRegionException: 150 times, servers with issues: my161208.cm6:60020,
at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatchCallback(HConnectionManager.:1600)
at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatch(HConnectionManager.java:1376)
at org.apache.hadoop.hbase.client.HTable.flushCommits(HTable.java:916)复制代码
2)读端也抛出类似异常信息:org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=10, exceptions:
Mon Oct 29 14:03:09 CST 2012, org.apache.hadoop.hbase.client.ScannerCallable@3740fb20, org.apache.hadoop.hbase.NotServingRegionException: org.apache.hadoop.hbase.NotServingRegionException: xxxxxx,\x0FP\x8D\xC3\xDB:\x00\x00V6,9.bd63dc25e78fba17ad6c. is closing复制代码
以上异常,在压测期间周期性地出现,HBase集群由此出现了短暂的不可服务期。2. 排查问题通过查看HBase Master运行日志,结合客户端抛出异常的时刻,发现当时HBase集群内正在进行Region的Split和不同机器之间的Region Balance,那么,为什么会周期性频繁触发以上过程呢?而且是发生在压测期间(数据量与平时相比大几倍)。下面结合表的设计来分析一下:1)由于表中rowkey有时间字段,因此每天都需要新创建Region,同时由于写入数据量大,进一步触发了HBase的Region Split操作,这一过程一般耗时较长(测试时从线上日志来看,平均为10秒左右,Region大小为4GB),且Region Split操作触发较为频繁;2)同时由于Region Split操作导致Region分布不均匀,进而触发HBase自动做Region Balance操作,Region迁移过程中也会导致Region下线,这一过程耗时较长(测试时从线上日志来看,平均为20秒左右)。3. 解决问题首先,从客户端考虑,其实就是要保证Region下线不可服务期间,读写请求能够在集群恢复后继续,具体可以采取如下措施:1)对于写端,可以将未写入成功的记录,添加到一个客户端缓存中,隔一段时间后交给一个后台线程统一重新提交一次;也可以通过setAutoFlush(flase, false)保证提交失败的记录不被抛弃,留在客户端writeBuffer中等待下次writeBuffer满了后再次尝试提交,直到提交成功为止。2)对于读端,捕获异常后,可以采取休眠一段时间后进行重试等方式。3)当然,还可以根据实际情况合理调整hbase.client.retries.number和hbase.client.pause配置选项。然后,从服务端考虑,需要分别针对Region Split和Region Balance进行解决:1)由于建表时,我们已经考虑到了数据在不同Region Server上的均匀分布,而且预先在不同Region Server上创建并分配了相同数目的Region,那么考虑到为了集群能够在实际线上环境下提供稳定的服务,可以选择关掉HBase的Region自动Balance功能,当然关掉后可以选择在每天读写压力小的时候(如凌晨后)触发执行一次Balance操作即可。2)接下来,Region总是被创建,不能被复用的问题该如何解决呢?根本原因是rowkey中包含了timestamp字段,而每时每刻timestamp总是向上增长的。但是,使用方确实需要能够根据timestamp字段进行顺序scan操作,因此,timestamp字段必须保留。据此,这里给出两种解决思路:一种常用方法是将表按照时间分表,例如按天进行分表,这样可以通过预先建表创建好Region分区,避免实际读写过程中频繁触发Region Split等过程,但是这一方法的缺点是每天需要预先建好表,而这一DDL过程可能出现问题进而导致读写出现问题,同时跨天时读写端也需要做出适应,调整为读写新创建的表。其实,我们可以换一种思路,通过修改表的rowkey结构,将timestamp字段改成一个周期循环的timestamp,如取timestamp % TS_MODE后的值,其中TS_MODE须大于等于表的TTL时间周期,这样才能保证数据不会被覆盖掉。经过这样改造后,即可实现Region的复用,避免Region的无限上涨。对于读写端的变更也较小,读写端操作时只需将timestamp字段取模后作为rowkey进行读写,另外,读端需要考虑能适应scan扫描时处理[startTsMode, endTsMode]和[endTsMode, startTsMode]两种情况。
4. 总结的话以上仅是本人结合实际项目中遇到的问题进行了概括总结,仅供参考。欢迎讨论交流。
| 文章可以转载,请以超链接形式标明文章原始出处和作者信息网址: 推荐:HBase 0.92版本之后,Region Server的Compact过程根据待合并的文件大小分为small compaction和large compaction两种,由此可能导致在集群写入量大的时候Compact占用过多的网络出口带宽。本文将详细描述集群使用过程中遇到这一问题的排查过程及其解决方法。1. 发现问题HBase集群(版本为0.94.0)运行过程中,发现5台Region Server的网络出口带宽经常维持在100MB/s以上,接近到网卡的极限;同时Region Server的机器load负载也很高,高峰时候能够达到30~50。2. 排查问题1、集群实际运行过程中,观察到Region Server服务端的网卡,平均每台写入流量大概60MB/s(此时写入量已经很大了);读出流量90MB/s,有时甚至突破100MB/s(注:每台机器都是千兆网卡);2、观察实际的写入数据量在每秒5w tps左右,单条记录平均大小为1KB,大概会占用50MB/s左右的网卡入口带宽请求量,和观察到的现象一致;3、观察查询量在每秒6w qps左右,单条记录平均大小为1KB,大概会占用60MB/s左右的网卡出口带宽请求量,奇怪的是实际观察到有接近甚至超过100MB/s的网络出口带宽请求量,多出了40MB/s左右的网络出口带宽;4、经分析排查确定导致上述过程的原因,可能是HBase服务端由于写入量过大频繁触发compaction过程,而compaction是需要读HBase数据的,因此占据了相当部分的网络出口带宽;5、结合对相关源码org/apache/hadoop/hbase/regionserver/CompactSplitThread.java的分析,决定对HBase集群配置做出变更(具体见下一小节),主要目的是减少compaction的发生;6、接下来,观察到Region Server的网络利用率明显降低,一般进出口带宽能维持在70MB/s以下。3. 解决问题HBase 0.92版本之后增加了关于compact的配置选项,compact分为small compaction和large compaction两个线程池执行(默认都是各有1个线程,具体源代码见:org/apache/hadoop/hbase/regionserver/CompactSplitThread.java),由于compact过程需要从HBase集群读取数据,因此实际运行中导致了compact占用大量网络出口流量,解决方案为选择性地关闭small compaction或large compaction。有以下两种变更方式均可解决:1)方案一(1) 修改hbase.paction.throttle为一个很大的值(如50GB),强制让所有compact都变为small compaction,减少compact的压力;(2) 将small compaction和large compaction线程数均设置为1,减少compact的压力(可不配置,系统默认也会将其初始化为1)。操作步骤:准备hbase-site.xml文件,添加或修改如下选项:&property&
& & &name&hbase.paction.throttle&/name&
& & &value&&/value&
&/property&
&property&
& & &name&hbase.paction.small&/name&
& & &value&1&/value&
&/property&
&property&
& & &name&hbase.paction.large&/name&
& & &value&1&/value&
&/property&复制代码
重启集群使配置生效。2)方案二将small compaction线程数均设置为0,从而关闭small compaction,只剩下large compaction,也可减少compact的压力。操作步骤:准备hbase-site.xml文件,添加或修改如下选项:&property&
& & &name&hbase.paction.small&/name&
& & &value&0&/value&
&/property&复制代码
重启集群使配置生效。
金牌会员, 积分 1669, 距离下一级还需 1331 积分
论坛徽章:4
本帖最后由 ehu4ever 于
12:04 编辑
折腾了一天两夜,
NotServingRegionException时,
马上下线这个regionserver,
这是个不错的策略……&&
另外,通过实践,调试好
network i/o, disk i/o与regionserver的数量之间的配比,
我想这个应该是系统稳定的基石吧?& &
论坛徽章:4
好复杂的Hbase!
扫一扫加入本版微信群8145人阅读
研究成果(42)
Hadoop相关(1)
本文出处:http://blog.csdn.net/chaijunkun/article/details/,转载请注明。由于本人不定期会整理相关博文,会对相应内容作出完善。因此强烈建议在原始出处查看此文。这些天研究HBase,写了一段Demo代码,具体如下:@Test
public void doTest() throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
Configuration config = HBaseConfiguration.create();
config.set(zkSetKey, zkConn);
HBaseAdmin hBaseAdmin =
hBaseAdmin = new HBaseAdmin(config);
ClusterStatus clusterStatus = hBaseAdmin.getClusterStatus();
ServerName master = clusterStatus.getMaster();
(&Master主机:{},端口号:{}&, master.getHostname(), master.getPort());
Collection&ServerName& servers = clusterStatus.getServers();
for (ServerName serverName : servers) {
(&Region主机{},端口号:{}&, serverName.getHostname(), serverName.getPort());
HTableDescriptor targetTableDesc =
targetTableDesc = hBaseAdmin.getTableDescriptor(TableName.valueOf(tableName));
(&表已经存在,显示信息&);
(&属性:{}&, targetTableDesc.toString());
}catch(TableNotFoundException notFound){
(&表不存在,创建&);
HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(tableName));
HColumnDescriptor hcd_info = new HColumnDescriptor(&info&);
hcd_info.setMaxVersions(3);
HColumnDescriptor hcd_data = new HColumnDescriptor(&data&);
htd.addFamily(hcd_info);
htd.addFamily(hcd_data);
hBaseAdmin.createTable(htd);
(&创建成功&);
targetTableDesc = hBaseAdmin.getTableDescriptor(TableName.valueOf(tableName));
(&属性:{}&, targetTableDesc.toString());
TableName[] listTableNames = hBaseAdmin.listTableNames();
if (listTableNames == null){
for (TableName tableName : listTableNames) {
(&表名:{}&, tableName.getNameAsString());
IOUtils.closeQuietly(hBaseAdmin);
}运行这段代码,程序会卡在第28行不动,也就是创建表操作,并且没有报出任何异常,其它的读取操作却很快(例如获取集群状态、列出所有表等操作)。于是本人陷入了深深地思考……在CSDN找到了一种类似的情况:主要是说HBase所依赖的HDFS进入了安全模式,需要手动退出该模式(运行命令:hdfs dfsadmin -safemode leave)。可是我查询当前的HDFS安全模式状态(hdfs dfsadmin -safemode get)时得到的信息是:Safe mode is OFF,也就是说根本没在安全模式下。后来偶然地过了一段时间再去看日志发现如下信息:#1, waiting for some tasks to finish. Expected max=0, tasksSent=9, tasksDone=8, currentTasksDone=8, retries=8 hasError=false, tableName=demo_table
#1, waiting for some tasks to finish. Expected max=0, tasksSent=10, tasksDone=9, currentTasksDone=9, retries=9 hasError=false, tableName=demo_table
#1, table=demo_table, attempt=10/35 failed 1 ops, last exception: java.net.UnknownHostException: unknown host:
on ,698289, tracking started Fri Mar 13 11:41:19 CST 2015, retrying after 10037 ms, replay 1 ops.最后一行的主机名:和引起了我的注意。因为我的测试环境为3台实体服务器,配置如下:IP地址hosts文件配置的主机名linux系统的hostnameHBase角色HDFS角色192.168.1.21hd-21test-21MasterServerNameNode、DataNode、ZooKeeper192.168.1.22hd-22test-22RegionServerNameNode、DataNode、ZooKeeper192.168.1.23hd-23test-23RegionServerDataNode、ZooKeeper另外,因为是测试环境,在192.168.1.22这台机器上还添加了如下hosts信息:192.168.1.22
192.168.1.22 简单来说就是hosts文件中配置的主机名和真实主机名不一致,并且还加入了额外的hosts配置信息干扰到了正确解析主机名。我运行demo程序的工作机没有配置任何额外的hosts,连接ZooKeeper时直接使用的IP地址,但是HBase Client 底层在进行操作时可能引入了主机名反向连接,作为完全干净的工作机当然找不到对应的服务器,就不断地在后台重试导致生成了上述的日志。当我把出现问题的两个hosts记录加入到工作机后,问题解决。经验:通过上述错误可知,Hadoop集群中hostname一定要与hosts文件中配置的名称一致,并且力求保证集群映射关系的纯净,不要把其他不相干的业务也部署在其中,引起不必要的麻烦。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1119221次
积分:8626
积分:8626
排名:第2337名
原创:63篇
转载:12篇
评论:550条
【我是谁】:一个有点文艺范的软件工程师
【怎么交流】:如有疑问,请在相关文章后提出问题或私信给我,我基本每天都上线
在CSDN代码库中我将分享比较完整的代码示例和开源项目,欢迎大家fork或向我索取commit权限
阅读:16329HBase写入操作卡住长时间不返回的因分析 - 数据库服务器 - 次元立方网 - 电脑知识与技术互动交流平台
HBase写入操作卡住长时间不返回的因分析
本文出处:http://blog.csdn.net/chaijunkun/article/details/,转载请注明。由于本人不定期会整理相关博文,会对相应内容作出完善。因此强烈建议在原始出处查看此文。这些天研究HBase,写了一段Demo代码,具体如下:@Test
public void doTest() throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
Configuration config = HBaseConfiguration.create();
config.set(zkSetKey, zkConn);
HBaseAdmin hBaseAdmin =
hBaseAdmin = new HBaseAdmin(config);
ClusterStatus clusterStatus = hBaseAdmin.getClusterStatus();
ServerName master = clusterStatus.getMaster();
(&Master主机:{},端口号:{}&, master.getHostname(), master.getPort());
Collection&ServerName& servers = clusterStatus.getServers();
for (ServerName serverName : servers) {
(&Region主机{},端口号:{}&, serverName.getHostname(), serverName.getPort());
HTableDescriptor targetTableDesc =
targetTableDesc = hBaseAdmin.getTableDescriptor(TableName.valueOf(tableName));
(&表已经存在,显示信息&);
(&属性:{}&, targetTableDesc.toString());
}catch(TableNotFoundException notFound){
(&表不存在,创建&);
HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(tableName));
HColumnDescriptor hcd_info = new HColumnDescriptor(&info&);
hcd_info.setMaxVersions(3);
HColumnDescriptor hcd_data = new HColumnDescriptor(&data&);
htd.addFamily(hcd_info);
htd.addFamily(hcd_data);
hBaseAdmin.createTable(htd);
(&创建成功&);
targetTableDesc = hBaseAdmin.getTableDescriptor(TableName.valueOf(tableName));
(&属性:{}&, targetTableDesc.toString());
TableName[] listTableNames = hBaseAdmin.listTableNames();
if (listTableNames == null){
for (TableName tableName : listTableNames) {
(&表名:{}&, tableName.getNameAsString());
IOUtils.closeQuietly(hBaseAdmin);
}运行这段代码,程序会卡在第28行不动,也就是创建表操作,并且没有报出任何异常,其它的读取操作却很快(例如获取集群状态、列出所有表等操作)。于是本人陷入了深深地思考……在CSDN找到了一种类似的情况:http://blog.csdn.net/lxpbs8851/article/details/8287471主要是说HBase所依赖的HDFS进入了安全模式,需要手动退出该模式(运行命令:hdfs dfsadmin -safemode leave)。可是我查询当前的HDFS安全模式状态(hdfs dfsadmin -safemode get)时得到的信息是:Safe mode is OFF,也就是说根本没在安全模式下。后来偶然地过了一段时间再去看日志发现如下信息:#1, waiting for some tasks to finish. Expected max=0, tasksSent=9, tasksDone=8, currentTasksDone=8, retries=8 hasError=false, tableName=demo_table
#1, waiting for some tasks to finish. Expected max=0, tasksSent=10, tasksDone=9, currentTasksDone=9, retries=9 hasError=false, tableName=demo_table
#1, table=demo_table, attempt=10/35 failed 1 ops, last exception: java.net.UnknownHostException: unknown host:
on ,698289, tracking started Fri Mar 13 11:41:19 CST 2015, retrying after 10037 ms, replay 1 ops.最后一行的主机名:和引起了我的注意。因为我的测试环境为3台实体服务器,配置如下:IP地址hosts文件配置的主机名linux系统的hostnameHBase角色HDFS角色192.168.1.21hd-21test-21MasterServerNameNode、DataNode、ZooKeeper192.168.1.22hd-22test-22RegionServerNameNode、DataNode、ZooKeeper192.168.1.23hd-23test-23RegionServerDataNode、ZooKeeper另外,因为是测试环境,在192.168.1.22这台机器上还添加了如下hosts信息:192.168.1.22
192.168.1.22 简单来说就是hosts文件中配置的主机名和真实主机名不一致,并且还加入了额外的hosts配置信息干扰到了正确解析主机名。我运行demo程序的工作机没有配置任何额外的hosts,连接ZooKeeper时直接使用的IP地址,但是HBase Client 底层在进行操作时可能引入了主机名反向连接,作为完全干净的工作机当然找不到对应的服务器,就不断地在后台重试导致生成了上述的日志。当我把出现问题的两个hosts记录加入到工作机后,问题解决。经验:通过上述错误可知,Hadoop集群中hostname一定要与hosts文件中配置的名称一致,并且力求保证集群映射关系的纯净,不要把其他不相干的业务也部署在其中,引起不必要的麻烦。
延伸阅读:
在一个需要低延时响应的hbase集群中,使用hbase默认的...
本教程为 李华明 编著的iOS-Cocos2d游戏开发系列教程:教程涵盖关于i......
专题主要学习DirectX的初级编程入门学习,对Directx11的入门及初学者有......
&面向对象的JavaScript&这一说法多少有些冗余,因为JavaScript 语言本......
Windows7系统专题 无论是升级操作系统、资料备份、加强资料的安全及管......

我要回帖

更多关于 hbase 连接池代码 的文章

 

随机推荐