一、内存优化
HBase操作过程中需要大量的内存开销,毕竟Table是可以缓存在内存中的,一般会分配整个可用内存的70%给HBase的Java堆。但是不建议分配非常大的堆内存,因为GC过程持续太久会导致RegionServer处于长期不可用状态,一般16-48G内存就可以了,如果因为框架占用内存过高导致内存不足,框架一样会被系统服务拖死。
二、基础优化
1、允许在HDFS的文件中追加内容:hdfs-site.xml、hbase-site.xml属性:dfs.support.append解释:开启HDFS追加同步,可以优秀的配合HBase的数据同步和持久化,默认值为true。2、优化DataNode允许的最大文件打开数:hdfs-site.xml属性:dfs.datanode.max.transfer.threads解释:HBase一般都会同一时间操作大量的文件,根据集群的数量和规模以及数据动作,设置为4096或者更高。默认值为4096。3、优化延迟高的数据操作的等待时间:hdfs-site.xml属性:dfs.image.transfer.timeout解释:如果对于某一次数据操作来说,延迟非常高,socket需要等待更长的时间,建议把该值设置为更大的值(默认60000毫秒),以确保socket不会timeout掉。4、优化数据的写入效率:mappred-site.xml属性:mapreduce.map.output.compressmapreduce.map.output.compress.codec解释:开启这两个数据可以大大提高文件的写入效率,减少写入时间,第一个属性值修改为true,第二个属性值修改为:org.apache.hadoop.io.compress.GzipCodec或者其他压缩方式。5、设置RPC监听数量:hbase-site.xml属性:Hbase.regionserver.handler.count解释:默认值为30,用于指定RPC监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值。6、优化HStore文件大小:hbase-site.xml属性:HBase.hregion.max.filesize解释:默认值10737418240(10GB),如果需要运行Hbase的MR任务,可以减小此值,因为一个region对应一个map任务,如果单个region过大,会导致map任务执行时间过长。该值的意思就是,如果HFile的大小达到这个数值,则这个region会被切分成两个HFile。7、优化HBase客户端缓存:hbase-site.xml属性:Hbase.client.write.buffer解释:用于指定HBase客户端缓存,增大该值可以减少RPC调用次数,但是会消耗更多的内存,反之则反之;一般设置该值可以达到减少RPC次数的目的即可。8、指定scan.next扫描HBase所获取的行数属性:Hbase.client.scanner.caching解释:用于指定scan.next方法获取的默认行数,值越大,消耗内存越大。9、flush、compact、split机制当MemStore达到阈值,将MemStore中的数据Flush进StoreFile;compact机制则是把flush出来的小文件合并成大的StoreFile文件;split则是当Region到达阈值,会把过大的Region一分二。涉及的属性:hbase.hregion.memstore.flush.size:134217728解释:Memstore的默认阈值,当HRegion内所有的Memstore大小总和超过指定值时,flush该HRegion的所有memstore。RegionServer的flush是通过将请求添加一个队列,模拟生产消费模型来进行异步处理的,那这里就有一个问题,当队列来不及消费,产生大量积压请求时,可能会导致内存徒增,最坏的情况就是OOM。hbase.regionserver.global.memstore.upperLimit:0.4hbase.regionserver.global.memstore.lowerLimit:0.38解释:当MemStore使用内存总量到达hbase.regionserver.global.memstore.upperLimit指定值时,将会有多个MemStore flush到文件中,MemStore flush顺序是按照大小降序执行的,直到刷新到MemStore使用内存略小于lowerLimit。
优化不是必要的,更重要的是进行预分区和进行合理的rowkey设计。
三、其他
3.1、Column Family
不要在一张表里定义太多的column family。目前HBase并不能很好的处理超过2~3个column family。因为某个 column family 在flush的时候,它邻近的 column family 也会因关联效应被触发flush,最终导致系统产生更多的I/O。
3.2、In Memory
创建表的时候,可以通过HColumnDescriptor.setInMemory(true) 将表放到 RegionServer 的缓存中,保证在读取的时候被cache命中。用在读取比较频繁的列族上。
3.3、Max Version
创建表的时候,可以通过 HColumnDescriptor.setMaxVersions(int maxVersions) 设置表中数据的最大版本,如果只需要保存最新版本的数据,那么可以设置为1。
3.4、Time To Live
创建表的时候,可以通过 HColumnDescriptor.setTimeToLive(int timeToLive) 设置表中数据的存储生命周期,过期的数据将被自动删除,例如如果只需要存储最近两天的数据,那么设置为setTimeToLive(2243600) ,单位秒。 
默认 TTL => ‘FOREVER’ 表示永久保存。
3.5、Compact & Split







四、写表操作
4.1、HTable参数设置
1、Write Buffer
通过调用HTable.setWriteBufferSize(writeBufferSize) 方法可以设置HTable客户端的写buffer大小,如果新设置的buffer小于当前写buffer中的数据时,buffer将会被flush到服务端。其中writeBufferSize的单位是byte字节数,可以根据实际写入数据量的多少来设置该值。
默认大小是2MB(即2097152字节),这个大小比较适中,一般用户插入HBase中的数据都相当小,即每次插入的数都远小于缓冲区的大小。如果需要存储交到的数据,通常需要考虑增大这个数值,从而允许客户端更高效地将一定数据量的数据组成一组,通过RPC请求来执行。
或者在配置修改参数,hbase.client.write.buffer , 单位字节。
2、Auto Flush
调用HTable.setAutoFlushTo(false)方法可以将HTable写客户端字段flush关闭,这样可以批量写入数据到HBase,而不是有一条put就执行一次更新,只有当put填满客户端写缓存时,才实际向HBase服务端发起写请求。默认auto flush是开启的。
3、WAL Flag
一般只有数据成功写入到WAL后,再往MemStore写数据,这样就会造成写效率低。对于不是很重要的数据,可以调用Put.setWriteToWAL(false) 或者 Delete.setWriteToWAL(false) ,在PUT/DELETE 时放弃写WAL日志,提高数据写入性能。但是这样会在出现RegionServer宕机时无法根据WAL日志进行数据恢复。
4、批量写,一次提交多个Put。
5、多线程写,可以创建多个HTable,每个线程负责各自的客户端。
