1、服务端调优node
一、参数配置redis
1)、hbase.regionserver.handler.count:该设置决定了处理RPC的线程数量,默认值是10,一般能够调大,好比:150,当请求内容很大(上MB,好比大的put、使用缓存的scans)的时候,若是该值设置过大则会占用过多的内存,致使频繁的GC,或者出现OutOfMemory,所以该值不是越大越好。spring
2)、hbase.hregion.max.filesize :配置region大小,0.94.12版本默认是10G,region的大小与集群支持的总数据量有关系,若是总数据量小,则单个region太大,不利于并行的数据处理,若是集群需支持的总数据量比较大,region过小,则会致使region的个数过多,致使region的管理等成本太高,若是一个RS配置的磁盘总量为3T*12=36T数据量,数据复制3份,则一台RS服务器能够存储10T的数据,若是每一个region最大为10G,则最多1000个region,如此看,94.12的这个默认配置仍是比较合适的,不过若是要本身管理split,则应该调大该值,而且在建表时规划好region数量和rowkey设计,进行region预建,作到必定时间内,每一个region的数据大小在必定的数据量之下,当发现有大的region,或者须要对整个表进行region扩充时再进行split操做,通常提供在线服务的hbase集群均会弃用hbase的自动split,转而本身管理split。apache
3)、hbase.hregion.majorcompaction:配置major合并的间隔时间,默认为1天,可设置为0,禁止自动的major合并,可手动或者经过脚本按期进行major合并,有两种compact:minor和major,minor一般会把数个小的相邻的storeFile合并成一个大的storeFile,minor不会删除标示为删除的数据和过时的数据,major会删除需删除的数据,major合并以后,一个store只有一个storeFile文件,会对store的全部数据进行重写,有较大的性能消耗。编程
4)、hbase.hstore.compactionThreshold:HStore的storeFile数量>= compactionThreshold配置的值,则可能会进行compact,默认值为3,能够调大,好比设置为6,在按期的major compact中进行剩下文件的合并。缓存
5)、 hbase.hstore.blockingStoreFiles:HStore的storeFile的文件数大于配置值,则在flush memstore前先进行split或者compact,除非超过hbase.hstore.blockingWaitTime配置的时间,默认为7,可调大,好比:100,避免memstore不及时flush,当写入量大时,触发memstore的block,从而阻塞写操做。tomcat
6)、hbase.regionserver.global.memstore.upperLimit:默认值0.4,RS全部memstore占用内存在总内存中的upper比例,当达到该值,则会从整个RS中找出最须要flush的region进行flush,直到总内存比例降至该数限制如下,而且在降至限制比例如下前将阻塞全部的写memstore的操做,在以写为主的集群中,能够调大该配置项,不建议太大,由于block cache和memstore cache的总大小不会超过0.8,并且不建议这两个cache的大小总和达到或者接近0.8,避免OOM,在偏向写的业务时,可配置为0.45,memstore.lowerLimit保持0.35不变,在偏向读的业务中,可调低为0.35,同时memstore.lowerLimit调低为0.3,或者再向下0.05个点,不能过低,除非只有很小的写入操做,若是是兼顾读写,则采用默认值便可。服务器
7)、hbase.regionserver.global.memstore.lowerLimit:默认值0.35,RS的全部memstore占用内存在总内存中的lower比例,当达到该值,则会从整个RS中找出最须要flush的region进行flush,配置时需结合memstore.upperLimit和block cache的配置。网络
8)、file.block.cache.size:RS的block cache的内存大小限制,默认值0.25,在偏向读的业务中,能够适当调大该值,具体配置时需试hbase集群服务的业务特征,结合memstore的内存占比进行综合考虑。session
9)、hbase.hregion.memstore.flush.size:默认值128M,单位字节,超过将被flush到hdfs,该值比较适中,通常不须要调整。
10)、hbase.hregion.memstore.block.multiplier:默认值2,若是memstore的内存大小已经超过了hbase.hregion.memstore.flush.size的2倍,则会阻塞memstore的写操做,直到降至该值如下,为避免发生阻塞,最好调大该值,好比:4,不可太大,若是太大,则会增大致使整个RS的memstore内存超过memstore.upperLimit限制的可能性,进而增大阻塞整个RS的写的概率。若是region发生了阻塞会致使大量的线程被阻塞在到该region上,从而其它region的线程数会降低,影响总体的RS服务能力,例如:
开始阻塞:
解开阻塞:
从10分11秒开始阻塞到10分20秒解开,总耗时9秒,在这9秒中没法写入,而且这期间可能会占用大量的RS handler线程,用于其它region或者操做的线程数会逐渐减小,从而影响到总体的性能,也能够经过异步写,并限制写的速度,避免出现阻塞。
11)、hfile.block.index.cacheonwrite:在index写入的时候容许put无根(non-root)的多级索引块到block cache里,默认是false,设置为true,或许读性能更好,可是是否有反作用还需调查。
12)、io.storefile.bloom.cacheonwrite:默认为false,需调查其做用。
13)、hbase.regionserver.regionSplitLimit:控制最大的region数量,超过则不能够进行split操做,默认是Integer.MAX,可设置为1,禁止自动的split,经过人工,或者写脚本在集群空闲时执行。若是不由止自动的split,则当region大小超过hbase.hregion.max.filesize时会触发split操做(具体的split有必定的策略,不只仅经过该参数控制,前期的split会考虑region数据量和memstore大小),每次flush或者compact以后,regionserver都会检查是否须要Split,split会先下线老region再上线split后的region,该过程会很快,可是会存在两个问题:一、老region下线后,新region上线前client访问会失败,在重试过程当中会成功可是若是是提供实时服务的系统则响应时长会增长;二、split后的compact是一个比较耗资源的动做。
14)、Jvm调整:
a、内存大小:master默认为1G,可增长到2G,regionserver默认1G,可调大到10G,或者更大,zk并不耗资源,能够不用调整;
b、垃圾回收:待研究。
二、其它调优
1)、列族、rowkey要尽可能短,每一个cell值均会存储一次列族名称和rowkey,甚至列名称也要尽可能短,如下截图是表test2的数据和存入hdfs后的文件内容:
由上图可见:短的列族名称、rowkey、列名称对最终的文件内容大小影响很大。
2)、RS的region数量:通常每一个RegionServer不要过1000,过多的region会致使产生较多的小文件,从而致使更多的compact,当有大量的超过5G的region而且RS总region数达到1000时,应该考虑扩容。
3)、建表时:
a、若是不须要多版本,则应设置version=1;
b、 开启lzo或者snappy压缩,压缩会消耗必定的CPU,可是,磁盘IO和网络IO将得到极大的改善,大体能够压缩4~5倍;
c、合理的设计rowkey,在设计rowkey时需充分的理解现有业务并合理预见将来业务,不合理的rowkey设计将致使极差的hbase操做性能;
d、合理的规划数据量,进行预分区,避免在表使用过程当中的不断split,并把数据的读写分散到不一样的RS,充分的发挥集群的做用;
e、列族名称尽可能短,好比:“f”,而且尽可能只有一个列族;
f、视场景开启bloomfilter,优化读性能。
2、Client端调优
一、hbase.client.write.buffer:写缓存大小,默认为2M,推荐设置为6M,单位是字节,固然不是越大越好,若是太大,则占用的内存太多;
二、hbase.client.scanner.caching:scan缓存,默认为1,过小,可根据具体的业务特征进行配置,原则上不可太大,避免占用过多的client和rs的内存,通常最大几百,若是一条数据太大,则应该设置一个较小的值,一般是设置业务需求的一次查询的数据条数,好比:业务特色决定了一次最多100条,则能够设置为100
三、设置合理的超时时间和重试次数,具体的内容会在后续的blog中详细讲解。
四、client应用读写分离
读和写分离,位于不一样的tomcat实例,数据先写入redis队列,再异步写入hbase,若是写失败再回存redis队列,先读redis缓存的数据(若是有缓存,须要注意这里的redis缓存不是redis队列),若是没有读到再读hbase。
当hbase集群不可用,或者某个RS不可用时,由于HBase的重试次数和超时时间均比较大(为保证正常的业务访问,不可能调整到比较小的值,若是一个RS挂了,一次读或者写,通过若干重试和超时可能会持续几十秒,或者几分钟),因此一次操做可能会持续很长时间,致使tomcat线程被一个请求长时间占用,tomcat的线程数有限,会被快速占完,致使没有空余线程作其它操做,读写分离后,写因为采用先写redis队列,再异步写hbase,所以不会出现tomcat线程被占满的问题, 应用还能够提供写服务,若是是充值等业务,则不会损失收入,而且读服务出现tomcat线程被占满的时间也会变长一些,若是运维介入及时,则读服务影响也比较有限。
五、若是把org.apache.hadoop.hbase.client.HBaseAdmin配置为spring的bean,则需配置为懒加载,避免在启动时连接hbase的Master失败致使启动失败,从而没法进行一些降级操做。
六、Scan查询编程优化:
1)、调整caching;
2)、若是是相似全表扫描这种查询,或者按期的任务,则能够设置scan的setCacheBlocks为false,避免无用缓存;
3)、关闭scanner,避免浪费客户端和服务器的内存;
4)、限定扫描范围:指定列簇或者指定要查询的列;
5)、若是只查询rowkey时,则使用KeyOnlyFilter可大量减小网络消耗;
做为hbase依赖的状态协调者ZK和数据的存储则HDFS,也须要调优:
ZK调优:
一、zookeeper.session.timeout:默认值3分钟,不可配置过短,避免session超时,hbase中止服务,线上生产环境因为配置为1分钟,出现过2次该缘由致使的hbase中止服务,也不可配置太长,若是太长,当rs挂掉,zk不能快速知道,从而致使master不能及时对region进行迁移。
二、zookeeper数量:至少5个节点。给每一个zookeeper 1G左右的内存,最好有独立的磁盘。 (独立磁盘能够确保zookeeper不受影响).若是集群负载很重,不要把Zookeeper和RegionServer运行在同一台机器上面。就像DataNodes 和 TaskTrackers同样,只有超过半数的zk存在才会提供服务,好比:共5台,则最多只运行挂2台,配置4台与3台同样,最多只运行挂1台。
三、hbase.zookeeper.property.maxClientCnxns:zk的最大链接数,默认为300,可配置上千
hdf调优:
一、dfs.name.dir: namenode的数据存放地址,能够配置多个,位于不一样的磁盘并配置一个NFS远程文件系统,这样nn的数据能够有多个备份
二、dfs.data.dir:dn数据存放地址,每一个磁盘配置一个路径,这样能够大大提升并行读写的能力
三、dfs.namenode.handler.count:nn节点RPC的处理线程数,默认为10,需提升,好比:60
四、dfs.datanode.handler.count:dn节点RPC的处理线程数,默认为3,需提升,好比:20
五、dfs.datanode.max.xcievers:dn同时处理文件的上限,默认为256,需提升,好比:8192
六、dfs.block.size:dn数据块的大小,默认为64M,若是存储的文件均是比较大的文件则能够考虑调大,好比,在使用hbase时,能够设置为128M,注意单位是字节
七、dfs.balance.bandwidthPerSec:在经过start-balancer.sh作负载均衡时控制传输文件的速度,默认为1M/s,可配置为几十M/s,好比:20M/s
八、dfs.datanode.du.reserved:每块磁盘保留的空余空间,应预留一些给非hdfs文件使用,默认值为0
九、dfs.datanode.failed.volumes.tolerated:在启动时会致使dn挂掉的坏磁盘数量,默认为0,即有一个磁盘坏了,就挂掉dn,能够不调整。
引用:http://itindex.net/detail/49632-hbase-%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98