hbase性能优化

Posted Hadoop大数据之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hbase性能优化相关的知识,希望对你有一定的参考价值。

一、hbase容错性

HMaster容错:Zookeeper重新选择一个新的HMaster。无HMaster的过程中,数据读取仍照常进行;无HMaster的过程中,region切分、负载均衡等无法进行。

HRegionServer容错:定时向Zookeeper汇报心跳,如果一段时间内未出现心跳,HMaster将该HRegionServer上的region重新分配到其它HRegionServer上,失效服务器上“预写”日志由主服务器进行分割并派送给新的HRegionServer。

Zookeeper容错:Zookeeper是一个可靠的服务,一般配置3个或5个Zookeeper实例。


二、hbase数据写入流程

Client写入 -> 存入MemStore,一直到MemStore满 ->Flush成一个StoreFile,直至增长到一定阈值 -> 发出compact合并操作 -> 多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除 -> 当StoreFile Compact后,逐步形成越来越大的StoreFile -> 单个StoreFile大小超过一定阈值后,触发split操作,把当前region split成2个region,region会下线,新split出的2个孩子region会被HMaster分配到相应的regionserver上,使得原先1个region的压力得以分流到2个region上。

由此过程可知,hbase只是增加数据,所有的更新和删除操作,都是compact阶段处理的,所以用户写操作只需要进入到内存即可立即返回,从而保证I/O高性能。

此外,hbase引入了HLog机制。在分布式系统环境中,无法避免系统出错或宕机,一旦HRegionServer意外退出,MemStore中的内存数据就会丢失,引入HLog就是防止这种情况,其工作机制如下:

每个HRegionServer中都会有一个HLog对象,HLog是一个实现WriteAheadLog的类,每次用户操作写入MemStore的同时,也会写一份数据到HLog文件,HLog文件定期会滚动出新,并删除旧的文件(已持久化到StoreFile中的数据)。当HRegionServer意外终止后,HMaster会通过Zookeeper感知,HMaster首先处理遗留的HLog文件,将不同region的log数据拆分,分别放到响应region目录下,然后再将失效的region重新分配,领取到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay(重放) HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复。


三、hbase查询工作原理


1、Client会通过内部缓存的相关的-ROOT-中的信息和.META中的信息直接连接与请求数据匹配的HRegionServer;

2、然后直接定位到该服务器上与客户请求对应的region,客户请求首先会查询该region在内存中的缓存MemStore(MemStore是一个按key字典排序的树形结构的缓冲区);

3、如果在MemStore中查到结果则直接将结果返回给Client;

4、在MemStore中没有查到匹配的数据,接下来会读已持久化的StoreFile文件中的数据。具体过程如下:

如果在blockcache中能查到需要的数据则返回结果,否则就去相应的StoreFile文件中读取一个block的数据,如果还没有读到要查的数据,就将该block数据放到HRegionServer的blockcache中,然后接着读下一个block数据,直到要找到要请求的数据并返回结果;如果遍历该region中的数据都没有查到要找的数据,最后直接返回null,表示没有找到匹配的数据。blockcache会在其大小大于阈值(heapsize*hfile.block.cache.size*0.85)后启动基于LRU算法淘汰机制,将最老最不常用的block删除。


四、性能调优

1、预先分区

默认情况下,在创建HBase表的时候会自动创建一个Region分区,当导入数据的时候,所有的HBase客户端都向这一个Region写数据,直到这个Region足够大了才进行切分。一种可以加快批量写入速度的方法是通过预先创建一些空的Regions,这样当数据写入HBase时,会按照Region分区情况,在集群内做数据的负载均衡。

2、rowkey优化设计

HBase中Rowkey是按照字典序存储,因此,设计Rowkey时,要充分利用排序特点,将经常一起读取的数据存储到一块,将最近可能会被访问的数据放在一块。此外,Rowkey若是递增的生成,建议不要使用正序直接写入Rowkey,而是采用reverse的方式反转Rowkey,使得Rowkey在HRegionServer上大致均衡分布。

3、减少列族数量

不要在一张表里定义太多的ColumnFamily。目前Hbase并不能很好的处理超过2~3个ColumnFamily的表。因为某个ColumnFamily在flush的时候,它邻近的ColumnFamily也会因关联效应被触发flush,最终导致系统产生更多的I/O。

4、缓存策略

创建表的时候,可以通过HColumnDescriptor.setInMemory(true)将表放到RegionServer的缓存中,保证在读取的时候被cache命中。

5、设置存储生命周期

创建表的时候,可以通过HColumnDescriptor.setTimeToLive(int timeToLive)设置表中数据的存储生命期,过期数据将自动被删除。

6、硬盘配置

每台RegionServer管理10~1000个Regions,每个Region在1~2G,则每台Server最少要10G,最大要1000*2G=2TB,考虑3备份,则要6TB。方案一是用3块2TB硬盘,二是用12块500G硬盘,带宽足够时,后者能提供更大的吞吐率,更细粒度的冗余备份,更快速的单盘故障恢复。

7、分配合适的内存给HRegionServer服务

在不影响其他服务的情况下,越大越好。

8、写数据的备份数

备份数与读性能成正比,与写性能成反比,且备份数影响高可用性。有两种配置方式,一种是将hdfs-site.xml拷贝到hbase的conf目录下,然后在其中添加或修改配置项dfs.replication的值为要设置的备份数,这种修改对所有的HBase用户表都生效,另外一种方式,是改写HBase代码,让HBase支持针对列族设置备份数,在创建表时,设置列族备份数,默认为3,此种备份数只对设置的列族生效。

9、WAL(预写日志)

可设置开关,表示HBase在写数据前用不用先写日志,默认是打开,关掉会提高性能,但是如果系统出现故障(负责插入的RegionServer挂掉),数据可能会丢失。配置WAL在调用JavaAPI写入时,设置Put实例的WAL,调用Put.setWriteToWAL(boolean)。

10、批量写

HBase的Put支持单条插入,也支持批量插入,一般来说批量写更快,节省来回的网络开销。

11、客户端一次从服务器拉取的数量

通过配置一次拉去的较大的数据量可以减少客户端获取数据的时间,但是它会占用客户端内存。有三个地方可进行配置:

1)在HBase的conf配置文件中进行配置hbase.client.scanner.caching;

2)通过调用HTable.setScannerCaching(int scannerCaching)进行配置;

3)通过调用Scan.setCaching(int caching)进行配置。三者的优先级越来越高。

12、HRegionServer的请求处理I/O线程数

较少的IO线程适用于处理单次请求内存消耗较高的Big Put场景(大容量单次Put或设置了较大cache的Scan,均属于Big Put)或ReigonServer的内存比较紧张的场景。

较多的IO线程,适用于单次请求内存消耗低,TPS要求(每秒事务处理量(TransactionPerSecond))非常高的场景。设置该值的时候,以监控内存为主要参考。

在 hbase-site.xml 配置文件中配置项为hbase.regionserver.handler.count。

13、region的大小设置

配置项为hbase.hregion.max.filesize,所属配置文件为hbase-site.xml,默认大小256M。

在当前ReigonServer上单个Reigon的最大存储空间,单个Region超过该值时,这个Region会被自动split成更小的Region。小Region对split和compaction友好,因为拆分Region或compact小Region里的StoreFile速度很快,内存占用低。缺点是split和compaction会很频繁,特别是数量较多的小Region不停地split、compaction,会导致集群响应时间波动很大,Region数量太多不仅给管理上带来麻烦,甚至会引发一些Hbase的bug。一般512M以下的都算小Region。大Region则不太适合经常split和compaction,因为做一次compact和split会产生较长时间的停顿,对应用的读写性能冲击非常大。

此外,大Region意味着较大的StoreFile,compaction时对内存也是一个挑战。如果你的应用场景中,某个时间点的访问量较低,那么在此时做compact和split,既能顺利完成split和compaction,又能保证绝大多数时间平稳的读写性能。compaction是无法避免的,split可以从自动调整为手动。只要通过将这个参数值调大到某个很难达到的值,比如100G,就可以间接禁用自动split(RegionServer不会对未到达100G的Region做split)。再配合RegionSplitter这个工具,在需要split时,手动split。手动split在灵活性和稳定性上比起自动split要高很多,而且管理成本增加不多,比较推荐online实时系统使用。内存方面,小Region在设置memstore的大小值上比较灵活,大Region则过大过小都不行,过大会导致flush时app的IO wait 增高,过小则因StoreFile过多影响读性能。

14、操作系统参数

Linux系统最大可打开文件数一般默认的参数值是1024,如果你不进行修改并发量上来的时候会出现“Too Many Open Files”的错误,导致整个HBase不可运行,你可以用ulimit -n 命令进行修改,或者修改/etc/security/limits.conf和/proc/sys/fs/file-max 的参数,具体如何修改可以去Google 关键字 “linux limits.conf ”

15、Jvm配置

修改 hbase-env.sh 文件中的配置参数,根据你的机器硬件和当前操作系统的JVM(32/64位)配置适当的参数:

HBASE_HEAPSIZE 4000 HBase使用的 JVM 堆的大小

HBASE_OPTS "‐server ‐XX:+UseConcMarkSweepGC"JVM GC 选项

HBASE_MANAGES_ZKfalse 是否使用Zookeeper进行分布式管理

16、持久化

重启操作系统后HBase中数据全无,你可以不做任何修改的情况下,创建一张表,写一条数据进行,然后将机器重启,重启后你再进入HBase的shell中使用 list 命令查看当前所存在的表,一个都没有了。是不是很杯具?没有关系你可以在hbase/conf/hbase-default.xml中设置hbase.rootdir的值,来设置文件的保存位置指定一个文件夹,例如:<value>file:///you/hbase-data/path</value>,你建立的HBase中的表和数据就直接写到了你的磁盘上,同样你也可以指定你的分布式文件系统HDFS的路径,例如:hdfs://NAMENODE_SERVER:PORT/HBASE_ROOTDIR,这样就写到了你的分布式文件系统上了。

17、缓冲区大小

hbase.client.write.buffer

这个参数可以设置写入数据缓冲区的大小,当客户端和服务器端传输数据,服务器为了提高系统运行性能开辟一个写的缓冲区来处理它,这个参数设置如果设置的大了,将会对系统的内存有一定的要求,直接影响系统的性能。

18. 扫描目录表

hbase.master.meta.thread.rescanfrequency

定义多长时间HMaster对系统表 root 和 meta 扫描一次,这个参数可以设置的长一些,降低系统的能耗。

19. split/compaction时间间隔

hbase.regionserver.thread.splitcompactcheckfrequency

这个参数是表示多久去RegionServer服务器运行一次split/compaction的时间间隔,当然split之前会先进行一个compact操作.这个compact操作可能是minorcompact也可能是major compact.compact后,会从所有的Store下的所有StoreFile文件最大的那个取midkey.这个midkey可能并不处于全部数据的mid中.一个row-key的下面的数据可能会跨不同的HRegion。

20. 缓存在JVM堆中分配的百分比

hfile.block.cache.size

指定HFile/StoreFile 缓存在JVM堆中分配的百分比,默认值是0.2,意思就是20%,而如果你设置成0,就表示对该选项屏蔽。

21. ZooKeeper客户端同时访问的并发连接数

hbase.zookeeper.property.maxClientCnxns

这项配置的选项就是从zookeeper中来的,表示ZooKeeper客户端同时访问的并发连接数,ZooKeeper对于HBase来说就是一个入口这个参数的值可以适当放大些。

22. memstores占用堆的大小参数配置

hbase.regionserver.global.memstore.upperLimit

在RegionServer中所有memstores占用堆的大小参数配置,默认值是0.4,表示40%,如果设置为0,就是对选项进行屏蔽。

23. Memstore中缓存写入大小

hbase.hregion.memstore.flush.size

Memstore中缓存的内容超过配置的范围后将会写到磁盘上,例如:删除操作是先写入MemStore里做个标记,指示那个value, column 或 family等下是要删除的,HBase会定期对存储文件做一个major compaction,在那时HBase会把MemStore刷入一个新的HFile存储文件中。如果在一定时间范围内没有做major compaction,而Memstore中超出的范围就写入磁盘上了。


以上是关于hbase性能优化的主要内容,如果未能解决你的问题,请参考以下文章

HBase入门笔记--读性能优化

hbase性能优化

HBase实际应用中的性能优化方法

详解HBase读写性能优化

详解HBase读写性能优化

详解HBase读写性能优化