zoukankan      html  css  js  c++  java
  • hbase读性能优化

    https://blog.csdn.net/zhanglh046/article/details/78517478

      使用HBase可能会遇到各种问题,有些是系统本身的设计的问题,有些是使用的问题,常见的问题:FULL GC异常导致宕机,RIT问题,写吞吐量太低以及读延迟较大。

      一般情况下,读请求延迟较大通常存在三种场景,分别为:

    1.  集群中某一个业务延迟较大,其他业务正常
    2.  整个集群所有业务反应延迟较大
    3.  某个业务起来之后集群其他部分业务延迟较大

    一 、HBase 客户端优化

    (1)Scan操作的缓存设置

      通常来讲一次scan会返回大量数据,因此客户端发起一次scan请求,实际并不会一次就将所有数据加载到本地,而是分成多次RPC请求进行加载,这样设计一方面是因为大量数据请求可能会导致网络带宽严重消耗进而影响其他业务,另一方面也有可能因为数据量太大导致本地客户端发生OOM。在这样的设计体系下用户会首先加载一部分数据到本地,然后遍历处理,再加载下一部分数据到本地处理,如此往复,直至所有数据都加载完成。数据加载到本地就存放在scan缓存中,默认100条数据大小。

      一般情况下,可能100条缓存数量就够了,但是遇到啊一些比较大的scan请求,可能查询几万或者10几万,那么缓存的命中率就很低了,如果scan请求很大,已经过万,hbase.client.scanner.caching,这个参数设置成500或者1000。

    (2)Get使用批量请求

      HBase分别提供了单条get以及批量get的API接口,使用批量get接口可以减少客户端到HRegionServer之间的RPC连接数,提高读取性能。另外需要注意的是,批量get请求要么成功返回所有请求数据,要么抛出异常。所以建议使用使用批量get[table.get(List<Get>)]进行读取请求

     (3)请求指定显示列簇或者列

      不同列族的数据分开存储在不同的目录下。如果一个表有多个列族,只是根据Rowkey而不指定列族进行检索的话不同列族的数据需要独立进行检索,性能必然会比指定列族的查询差很多,很多情况下甚至会有2倍~3倍的性能损失。所以建议在查询的时候指定列簇或者列进行精确的查找。

    (4)离线批量读取请求是否设置禁止缓存

      通常离线批量读取数据会进行一次性全表扫描,一方面数据量很大,另一方面请求只会执行一次。这种场景下如果使用scan默认设置,就会将数据从HDFS加载出来之后放到缓存。可想而知,大量数据进入缓存必将其他实时业务热点数据挤出,其他业务不得不从HDFS加载,进而会造成明显的读延迟毛刺。所以建议离线批量读取请求设置禁用缓存,scan.setBlockCache(false)

    二、 HBase服务器端优化

      一般服务端问题一旦导致业务读请求延迟较大的话,通常是集群级别的,即整个集群的业务都会反映读延迟较大。可以从4个方面入手:

    (1)读请求不均衡

      极端情况下假如所有的读请求都落在一台RegionServer的某几个Region上,那么首先会造成该RegionServer资源严重消耗,另外不能发挥集群的并发处理能力,落在该台RegionServer上的其他业务会因此受到很大的波及读请求不均衡不仅会造成本身业务性能很差,还会严重影响其他业务。当然,写请求不均衡也会造成类似的问题,可见负载不均衡是HBase的大忌。

      定位:所以建议观察所有RegionServer的读请求QPS曲线,确认是否存在读请求不均衡现象。

      解决:如果存在,则RowKey必须进行散列化处理(比如MD5散列),同时建表必须进行预分区处理。

    (2)BlockCache设置

      默认情况下BlockCache和Memstore的配置相对比较均衡(各占40%),可以根据集群业务进行修正,比如读多写少业务可以将BlockCache占比调大。另一方面,BlockCache的策略选择也很重要,不同策略对读性能来说影响并不是很大,但是对GC的影响却相当显著,尤其BucketCache的offheap模式下GC表现很优越。另外,HBase 2.0对offheap的改造(HBASE-11425)将会使HBase的读性能得到2~4倍的提升,同时GC表现会更好!

      所以建议观察所有RegionServer的缓存未命中率、配置文件相关配置项一级GC日志,确认BlockCache是否可以优化。如果缓存命中较低,建议使用offheap模式;

      JVM内存配置量 < 20G,BlockCache策略选择LRUBlockCache;否则选择BucketCache策略的offheap模式

    补充:HBase上RegionServer的cache主要分为两个部分,分别是memstore&blockcache,其中memstore主要用于写缓存,而blockcache用于读缓存。

    (3)HFile文件太多

      一个store可能包含很多的HFile文件,文件越多,检索所需的IO次数必然越多,读取延迟也就越高。文件数量通常取决于Compaction的执行策略,一般和两个配置参数有关:

      hbase.hstore.compactionThreshold 和 hbase.hstore.compaction.max.size,前者表示一个store中的文件数超过多少就应该进行合并,后者表示参数合并的文件大小最大是多少,超过此大小的文件不能参与合并。这两个参数不能设置太’松’(前者不能设置太大,后者不能设置太小),导致Compaction合并文件的实际效果不明显,进而很多文件得不到合并。这样就会导致HFile文件数变多。

      所以建议观察RegionServer级别以及Region级别的storefile数,确认HFile文件是否过多,hbase.hstore.compactionThreshold设置不能太大,默认是3个;设置需要根据Region大小确定,通常可以简单的认为hbase.hstore.compaction.max.size= RegionSize / hbase.hstore.compactionThreshold。

    (4) Compaction是否消耗系统资源过多

      Compaction是将小文件合并为大文件,提高后续业务随机读性能,但是也会带来IO放大以及带宽消耗问题(数据远程读取以及三副本写入都会消耗系统带宽)。正常配置情况下Minor Compaction并不会带来很大的系统资源消耗,除非因为配置不合理导致Minor Compaction太过频繁,或者Region设置太大情况下发生Major Compaction。观察系统IO资源以及带宽资源使用情况,再观察Compaction队列长度,确认是否由于Compaction导致系统资源消耗过多

    建议:

    # Minor Compaction设置:hbase.hstore.compactionThreshold设置不能太小,又不能设置太大,因此建议设置为5~6;hbase.hstore.compaction

    .max.size = RegionSize / hbase.hstore.compactionThreshold

    # Major Compaction设置:大Region读延迟敏感业务( 100G以上)通常不建议开启自动MajorCompaction,手动低峰期触发。小Region或者延迟不敏感业务可以开启Major Compaction,但建议限制流量

    三、 HBase 列簇设计优化

      Bloomfilter主要用来过滤不存在待检索RowKey或者Row-Col的HFile文件,避免无用的IO操作。它会告诉你在这个HFile文件中是否可能存在待检索的KV,如果不存在,就可以不用消耗IO打开文件进行seek。很显然,通过设置Bloomfilter可以提升随机读写的性能。

      Bloomfilter取值有两个,row以及rowcol,需要根据业务来确定具体使用哪种。如果业务大多数随机查询仅仅使用row作为查询条件,Bloomfilter一定要设置为row,否则如果大多数随机查询使用row+cf作为查询条件,Bloomfilter需要设置为rowcol。如果不确定业务查询类型,设置为row。

      所以建议任何业务都应该设置Bloomfilter,通常设置为row就可以,除非确认业务随机查询类型为row+cf,可以设置为rowcol

    四、HDFS 相关优化

      HDFS作为HBase最终数据存储系统,通常会使用三副本策略存储HBase数据文件以及日志文件。从HDFS的角度望上层看,HBase即是它的客户端,HBase通过调用它的客户端进行数据读写操作,因此HDFS的相关优化也会影响HBase的读写性能。这里主要关注如下三个方面:

    (1) Short-CircuitLocal Read(局部短路读)功能是否开启

      当前HDFS读取数据都需要经过DataNode,客户端会向DataNode发送读取数据的请求,DataNode接受到请求之后从硬盘中将文件读出来,再通过TPC发送给客户端。Short Circuit策略允许客户端绕过DataNode直接读取本地数据。可参考:

    http://blog.cloudera.com/blog/2013/08/how-improved-short-circuit-local-reads-bring-better-performance-and-security-to-hadoop/

    所以建议开启Short Circuit Local Read功能,可以参考:

    https://issues.apache.org/jira/browse/HDFS-5776

    (2)Hedged Read(两面读)功能是否开启

      HBase数据在HDFS中一般都会存储三份,而且优先会通过Short-Circuit Local Read功能尝试本地读。但是在某些特殊情况下,有可能会出现因为磁盘问题或者网络问题引起的短时间本地读取失败,为了应对这类问题,社区开发者提出了补偿重试机制 – Hedged Read。该机制基本工作原理为:客户端发起一个本地读,一旦一段时间之后还没有返回,客户端将会向其他DataNode发送相同数据的请求。哪一个请求先返回,另一个就会被丢弃。

      所以建议开启Hedged Read功能,具体参考 https://issues.apache.org/jira/browse/HDFS-5776

    (3)数据本地率是否太低

      数据本地率:HDFS数据通常存储三份,假如当前 RegionA 处于 Node1 上,数据a写入的时候三副本为(Node1,Node2,Node3),数据b写入三副本是(Node1,Node4,Node5),数据c写入三副本(Node1,Node3,Node5),可以看出来所有数据写入本地 Node1 肯定会写一份,数据都在本地可以读到,因此数据本地率是100%。现在假设 RegionA 被迁移到了 Node2 上,只有数据a在该节点上,其他数据(b和c)读取只能远程跨节点读,本地率就为33%(假设a,b和c的数据大小相同)。

      据本地率太低很显然会产生大量的跨网络IO请求,必然会导致读请求延迟较高,因此提高数据本地率可以有效优化随机读性能。数据本地率低的原因一般是因为Region迁移(自动balance开启、RegionServer宕机迁移、手动迁移等),因此一方面可以通过避免Region无故迁移来保持数据本地率,另一方面如果数据本地率很低,也可以通过执行major_compact提升数据本地率到100%

      所以避免Region无故迁移,比如关闭自动balance、RS宕机及时拉起并迁回飘走的Region等;在业务低峰期执行major_compact提升数据本地率

  • 相关阅读:
    c# DataTable获取某个列的集合
    DataTable中的select()用法(转)
    java中,数组toString()方法,数组常用操作
    C# 如何重写ToString函数及重写的意义,自定义类重写ToString()方法
    重写List 的ToString方法 -------C#
    设置响应报文头 image/jpeg
    response 设置响应头的常用几种方法
    [C#]Http请求报头设置
    HttpContext.Current.Session.Abandon() 大坑 要注意
    for循环拼接字符串去掉最后的逗号
  • 原文地址:https://www.cnblogs.com/guoyu1/p/13934255.html
Copyright © 2011-2022 走看看