Hadoop之Hbase从学习入门到精通2.doc

上传人:小** 文档编号:576085 上传时间:2018-10-31 格式:DOC 页数:77 大小:573.03KB
返回 下载 相关 举报
Hadoop之Hbase从学习入门到精通2.doc_第1页
第1页 / 共77页
Hadoop之Hbase从学习入门到精通2.doc_第2页
第2页 / 共77页
点击查看更多>>
资源描述

《Hadoop之Hbase从学习入门到精通2.doc》由会员分享,可在线阅读,更多相关《Hadoop之Hbase从学习入门到精通2.doc(77页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、|一、 HBase 性能调优我们经常看到一些文章吹嘘某产品如何如何快,如何如何强,而自己测试时却不如描述的一些数据。其实原因可能在于你还不是真正理解其内部结构,对于其性能调优方法不够了解。本文转自 TaoBao 的 Ken Wu 同学的博客,是目前看到比较完整的 HBase 调优文章。原文链接: HBase 性能调优因 官方 Book Performance Tuning 部分章节没有按配置项进行索引,不能达到快速查阅的效果。所以我以配置项驱动,重新整理了原文,并补充一些自己的理解,如有错误,欢迎指正。配置优化zookeeper.session.timeout默认值:3 分钟(180000ms

2、)说明:RegionServer 与 Zookeeper 间的连接超时时间。当超时时间到后,ReigonServer 会被 Zookeeper 从 RS 集群清单中移除,HMaster 收到移除通知后,会对这台 server 负责的 regions 重新 balance,让其他存活的 RegionServer接管.调优:这个 timeout 决定了 RegionServer 是否能够及时的 failover。设置成1 分钟或更低,可以减少因等待超时而被延长的 failover 时间。不过需要注意的是,对于一些 Online 应用,RegionServer 从宕机到恢复时间本身就很短的(网络闪断

3、,crash 等故障,运维可快速介入),如果调低timeout 时间,反而会得不偿失。因为当 ReigonServer 被正式从 RS 集群中移除时,HMaster 就开始做 balance 了(让其他 RS 根据故障机器记录的 WAL 日志进行恢复)。当故障的 RS 在人工介入恢复后,这个 balance 动作是毫无意义的,反而会使负载不均匀,给 RS 带来更多负担。特别是那些固定分配 regions 的场景。hbase.regionserver.handler.count默认值:10说明:RegionServer 的请求处理 IO 线程数。调优:这个参数的调优与内存息息相关。|较少的 IO

4、 线程,适用于处理单次请求内存消耗较高的 Big PUT 场景(大容量单次 PUT 或设置了较大 cache 的 scan,均属于 Big PUT)或 ReigonServer 的内存比较紧张的场景。较多的 IO 线程,适用于单次请求内存消耗低,TPS 要求非常高的场景。设置该值的时候,以监控内存为主要参考。这里需要注意的是如果 server 的 region 数量很少,大量的请求都落在一个region 上,因快速充满 memstore 触发 flush 导致的读写锁会影响全局 TPS,不是 IO 线程数越高越好。压测时,开启 Enabling RPC-level logging,可以同时监控

5、每次请求的内存消耗和 GC 的状况,最后通过多次压测结果来合理调节 IO 线程数。这里是一个案例 Hadoop and HBase Optimization for Read Intensive Search Applications,作者在 SSD 的机器上设置 IO 线程数为 100,仅供参考。hbase.hregion.max.filesize默认值:256M说明:在当前 ReigonServer 上单个 Reigon 的最大存储空间,单个 Region 超过该值时,这个 Region 会被自动 split 成更小的 region。调优:小 region 对 split 和 compac

6、tion 友好,因为拆分 region 或 compact小 region 里的 storefile 速度很快,内存占用低。缺点是 split 和compaction 会很频繁。特别是数量较多的小 region 不停地 split, compaction,会导致集群响应时间波动很大,region 数量太多不仅给管理上带来麻烦,甚至会引发一些 Hbase 的bug。一般 512 以下的都算小 region。大 region,则不太适合经常 split 和 compaction,因为做一次 compact 和split 会产生较长时间的停顿,对应用的读写性能冲击非常大。此外,大region 意味着

7、较大的 storefile,compaction 时对内存也是一个挑战。当然,大 region 也有其用武之地。如果你的应用场景中,某个时间点的访问量较低,那么在此时做 compact 和 split,既能顺利完成 split 和 compaction,又能保证绝大多数时间平稳的读写性能。既然 split 和 compaction 如此影响性能,有没有办法去掉?compaction 是无法避免的,split 倒是可以从自动调整为手动。只要通过将这个参数值调大到某个很难达到的值,比如 100G,就可以间接禁用自动 split(RegionServer 不会对未到达 100G 的 region 做

8、 split)。再配合 RegionSplitter 这个工具,在需要 split 时,手动 split。|手动 split 在灵活性和稳定性上比起自动 split 要高很多,相反,管理成本增加不多,比较推荐 online 实时系统使用。内存方面,小 region 在设置 memstore 的大小值上比较灵活,大 region 则过大过小都不行,过大会导致 flush 时 app 的 IO wait 增高,过小则因 store file过多影响读性能。hbase.regionserver.global.memstore.upperLimit/lowerLimit默认值:0.4/0.35uppe

9、rlimit 说明:hbase.hregion.memstore.flush.size 这个参数的作用是 当单个 memstore 达到指定值时,flush 该 memstore。但是,一台ReigonServer 可能有成百上千个 memstore,每个 memstore 也许未达到flush.size,jvm 的 heap 就不够用了。该参数就是为了限制 memstores 占用的总内存。当 ReigonServer 内所有的 memstore 所占用的内存总和达到 heap 的 40%时,HBase 会强制 block 所有的更新并 flush 这些 memstore 以释放所有 mem

10、store占用的内存。lowerLimit 说明: 同 upperLimit,只不过当全局 memstore 的内存达到 35%时,它不会 flush 所有的 memstore,它会找一些内存占用较大的 memstore,做个别flush,当然更新还是会被 block。lowerLimit 算是一个在全局 flush 导致性能暴跌前的补救措施。为什么说是性能暴跌?可以想象一下,如果 memstore 需要在一段较长的时间内做全量 flush,且这段时间内无法接受任何读写请求,对HBase 集群的性能影响是很大的。调优:这是一个 Heap 内存保护参数,默认值已经能适用大多数场景。它的调整一般是

11、为了配合某些专属优化,比如读密集型应用,将读缓存开大,降低该值,腾出更多内存给其他模块使用。这个参数会给使用者带来什么影响?比如,10G 内存,100 个 region,每个 memstore 64M,假设每个 region 只有一个 memstore,那么当 100 个 memstore 平均占用到 50%左右时,就会达到lowerLimit 的限制。假设此时,其他 memstore 同样有很多的写请求进来。在那些大的 region 未 flush 完,就可能又超过了 upperlimit,则所有 region 都会被 block,开始触发全局 flush。不过,除了你的内存非常小或你的应用

12、场景里大多数都是读,我觉得不需要去调这个参数。hfile.block.cache.size默认值:0.2|说明:storefile 的读缓存占用 Heap 的大小百分比,0.2 表示 20%。该值直接影响数据读的性能。调优:当然是越大越好,如果读比写少,开到 0.4-0.5 也没问题。如果读写较均衡,0.3 左右。如果写比读多,果断默认吧。设置这个值的时候,你同时要参考 hbase.regionserver.global.memstore.upperLimit ,该值是 memstore占 heap 的最大百分比,两个参数一个影响读,一个影响写。如果两值加起来超过 80-90%,会有 OOM

13、的风险,谨慎设置。hbase.hstore.blockingStoreFiles默认值:7说明:在 compaction 时,如果一个 Store(Coulmn Family)内有超过 7 个storefile 需要合并,则 block 所有的写请求,进行 flush,限制 storefile 数量增长过快。调优:block 写请求会影响当前 region 的性能,将值设为单个 region 可以支撑的最大 store file 数量会是个不错的选择,即允许 comapction 时,memstore 继续生成 storefile。最大 storefile 数量可通过 region size/

14、memstore size 来计算。如果你将 region size 设为无限大,那么你需要预估一个 region 可能产生的最大 storefile 数。hbase.hregion.memstore.block.multiplier默认值:2说明:当一个 region 里的 memstore 超过单个 memstore.size 两倍的大小时,block 该 region 的所有请求,进行 flush,释放内存。虽然我们设置了memstore 的总大小,比如 64M,但想象一下,在最后 63.9M 的时候,我 Put 了一个 100M 的数据,此时 memstore 的大小会瞬间暴涨到超过预

15、期的memstore.size。这个参数的作用是当 memstore 的大小增至超过memstore.size 时,block 所有请求,遏制风险进一步扩大。调优: 这个参数的默认值还是比较靠谱的。如果你预估你的正常应用场景(不包括异常)不会出现突发写或写的量可控,那么保持默认值即可。如果正常情况下,你的写请求量就会经常暴长到正常的几倍,那么你应该调大这个倍数并调整其他参数值,比如 hfile.block.cache.size 和hbase.regionserver.global.memstore.upperLimit/lowerLimit,以预留更多内存,防止 HBase server OO

16、M。其他启用 LZO 压缩|LZO 对比 Hbase 默认的 GZip,前者性能较高,后者压缩比较高,具体参见Using LZO Compression。对于想提高 HBase 读写性能的开发者,采用 LZO 是比较好的选择。对于非常在乎存储空间的开发者,则建议保持默认。不要在一张表里定义太多的 Column FamilyHbase 目前不能良好的处理超过包含 2-3 个 CF 的表。因为某个 CF 在 flush 发生时,它邻近的 CF 也会因关联效应被触发 flush,最终导致系统产生更多 IO。批量导入在批量导入数据到 Hbase 前,你可以通过预先创建 regions,来平衡数据的负载

17、。详见 Table Creation: Pre-Creating Regions避免 CMS concurrent mode failureHBase 使用 CMS GC。默认触发 GC 的时机是当年老代内存达到 90%的时候,这个百分比由 -XX:CMSInitiatingOccupancyFraction=N 这个参数来设置。concurrent mode failed 发生在这样一个场景:当年老代内存达到 90%的时候,CMS 开始进行并发垃圾收集,于此同时,新生代还在迅速不断地晋升对象到年老代。当年老代 CMS 还未完成并发标记时,年老代满了,悲剧就发生了。CMS 因为没内存可用不得不

18、暂停 mark,并触发一次全jvm 的 stop the world(挂起所有线程),然后采用单线程拷贝方式清理所有垃圾对象。这个过程会非常漫长。为了避免出现 concurrent mode failed,我们应该让 GC 在未到 90%时,就触发。通过设置 -XX:CMSInitiatingOccupancyFraction=N这个百分比, 可以简单的这么计算。如果你的 hfile.block.cache.size 和hbase.regionserver.global.memstore.upperLimit 加起来有 60%(默认),那么你可以设置 70-80,一般高 10%左右差不多。Hb

19、ase 客户端优化AutoFlush将 HTable 的 setAutoFlush 设为 false,可以支持客户端批量更新。即当 Put填满客户端 flush 缓存时,才发送到服务端。默认是 true。Scan Cachingscanner 一次缓存多少数据来 scan(从服务端一次抓多少数据回来 scan)。默认值是 1,一次只取一条。|Scan Attribute Selectionscan 时建议指定需要的 Column Family,减少通信量,否则 scan 操作默认会返回整个 row 的所有数据(所有 Coulmn Family)。Close ResultScanners通过 s

20、can 取完数据后,记得要关闭 ResultScanner,否则 RegionServer 可能会出现问题(对应的 Server 资源无法释放)。Optimal Loading of Row Keys当你 scan 一张表的时候,返回结果只需要 row key(不需要 CF, qualifier,values,timestaps)时,你可以在 scan 实例中添加一个filterList,并设置 MUST_PASS_ALL 操作,filterList 中add FirstKeyOnlyFilter 或 KeyOnlyFilter。这样可以减少网络通信量。Turn off WAL on Puts

21、当 Put 某些非重要数据时,你可以设置 writeToWAL(false),来进一步提高写性能。writeToWAL(false)会在 Put 时放弃写 WAL log。风险是,当RegionServer 宕机时,可能你刚才 Put 的那些数据会丢失,且无法恢复。启用 Bloom FilterBloom Filter 通过空间换时间,提高读操作性能二、 关于 HFile 的思考本文是一篇转载文章,原文作者郭鹏(逖靖寒),国内 Cassandra 领域的先驱者和实践者。资深软件开发工程师,擅长分布式应用程序的开发和使用,实践经验极其丰富。在本文中,作者推荐了 HFile 文件格式的经典论文,并

22、对HFile 的 block size 的应用进行了实例探讨。|0.90.x 版本的 HBase 中的文件是存储在 HFile 中的。关于 HFile 文件的详细介绍,可以查看这篇文章:hfile.pdf这篇文章中介绍了以下五点内容: HFile 的作用。 HFile 的格式。 HFile 的性能。 HFile 的使用注意事项。 HFile 的编程接口。HFile 中有一个很重要的参数,那就是 block size。如果我们写入 hfile 中的某一个 value 的值大于 block size 会怎么样?于是有如下的测试代码:/ create local file systemFileSys

23、tem fs = new RawLocalFileSystem();fs.setConf(new Configuration();/ block size = 1kbHFile.Writer hwriter = new HFile.Writer(fs,new Path(“hfile“), 1, (Compression.Algorithm) null, null);/ create key byte value = new byte8 * 1024;for (int i = 0; i 8 * 1024; i+) valuei = 0;/ add values to hfilefor (int

24、i = 0; i 10; i+) |hwriter.append(key, value);/ close hfilehwriter.close();上面的代码可以看出来,每一个 value 的值都是 8kb,已经超过了 hfile 预设的 1kb 的 block size。实际的写入情况是如果 value 大于 block size,那么就按照实际的情况来写。上面的测试用例执行完毕以后,整个 hile 文件只有 1 个 data block。这个 hfile 的读取代码如下:/ create local file systemFileSystem fs = new RawLocalFileSy

25、stem();fs.initialize(URI.create(“file:/“), new Configuration();fs.setConf(new Configuration();HFile.Reader hreader = new HFile.Reader(fs,new Path(“hfile“), null, false);/ loadFileInfohreader.loadFileInfo();HFileScanner hscanner = hreader.getScanner(false, false);/ seek to the start position of the h

26、file.hscanner.seekTo();/ print values.int index = 1;while (hscanner.next() System.out.println(“index: “ + index+);System.out.println(“key: “ + hscanner.getKeyString();System.out.println(“value: “ + hscanner.getValueString();/ close hfile.hreader.close();上面的代码将读取 hfile,并将这个文件中的所有 kv 打印出来。通过上面的测试可以看出:

27、如果某一个 key 有非常非常多的 value,那么查找这些 value 就无法通过索引去快速查找,而是需要通过遍历进行。|另外,JIRA 上面的 HBASE-3857 也提出了一种新的 HFile 格式,HFile v2他主要是针对现有 HFile 的两个主要缺陷提出来的: 暂用过多内存 启动加载时间缓慢有兴趣的朋友可以详细了解一下。三、 HBase 性能优化方法总结1. 表的设计1.1 Pre-Creating Regions默认情况下,在创建 HBase 表的时候会自动创建一个 region 分区,当导入数据的时候,所有的 HBase 客户端都向这一个 region 写数据,直到这个 r

28、egion 足够大了才进行切分。一种可以加快批量写入速度的方法是通过预先创建一些空的 regions,这样当数据写入 HBase 时,会按照 region 分区情况,在集群内做数据的负载均衡。有关预分区,详情参见: Table Creation: Pre-Creating Regions,下面是一个例子:1234567891011121314151617public static boolean createTable(HBaseAdmin admin, HTableDescriptor table, byte splits) throws IOException try admin.crea

29、teTable(table, splits); return true; catch (TableExistsException e) logger.info(“table “ + table.getNameAsString() + “ already exists“); / the table already exists. return false; public static byte getHexSplits(String startKey, String endKey, int numRegions) byte splits = new bytenumRegions-1; |1819

30、20212223242526BigInteger lowestKey = new BigInteger(startKey, 16); BigInteger highestKey = new BigInteger(endKey, 16); BigInteger range = highestKey.subtract(lowestKey); BigInteger regionIncrement = range.divide(BigInteger.valueOf(numRegions); lowestKey = lowestKey.add(regionIncrement); for(int i=0;

31、 i numRegions-1;i+) BigInteger key = lowestKey.add(regionIncrement.multiply(BigInteger.valueOf(i); byte b = String.format(“%016x“, key).getBytes(); splitsi = b; return splits; 1.2 Row KeyHBase 中 row key 用来检索表中的记录,支持以下三种方式: 通过单个 row key 访问:即按照某个 row key 键值进行 get 操作; 通过 row key 的 range 进行 scan:即通过设置 s

32、tartRowKey 和endRowKey,在这个范围内进行扫描; 全表扫描:即直接扫描整张表中所有行记录。在 HBase 中,row key 可以是任意字符串,最大长度 64KB,实际应用中一般为10100bytes,存为 byte字节数组,一般设计成定长的。row key 是按照字典序存储,因此,设计 row key 时,要充分利用这个排序特点,将经常一起读取的数据存储到一块,将最近可能会被访问的数据放在一块。举个例子:如果最近写入 HBase 表中的数据是最可能被访问的,可以考虑将时间戳作为 row key 的一部分,由于是字典序排序,所以可以使用Long.MAX_VALUE timestamp 作为 row key,这样能保证新写入的数据在读取时可以被快速命中。1.3 Column Family不要在一张表里定义太多的 column family。目前 Hbase 并不能很好的处理超过 23 个 column family 的表。因为某个 column family 在 flush 的时候,它邻近的 column family 也会因关联效应被触发 flush,最终导致系统产生更多的 I/O。感兴趣的同学可以对自己的 HBase 集群进行实际测试,从得到的测试结果数据验证一下。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com