接触hbase已经两年之久,但是真正的在实际项目中使用却只有半年的时间,使用过程中,一方面在在为hbase强大的性能兴奋之余,另一方面却也给我和我的团队造成了很多的麻烦,起初在使用我的水平也就停留在会用而已,根本谈不上优化,但是后来发现,如果想要把它用好,让它在你的业务中不出问题,那么就需要你针对自己的业务去进行优化,下面是我认为在使用中应当注意的几点问题:
1. 安装集群前
- 配置SSH无密码登陆
- DNS。HBase使用本地 hostname 才获得IP地址,正反向的DNS都是可以的。你还可以设置
hbase.regionserver.dns.interface
来指定主接口,设置hbase.regionserver.dns.nameserver
来指定nameserver,而不使用系统带的 - 安装NTP服务,并配置和检查crontab是否生效
- 操作系统调优,包括最大文件句柄,nproc hard 和 soft limits等等
-
conf/hdfs-site.xml
里面的dfs.datanode.max.xcievers
参数,至少要有4096,建议这个值设置的大一点,要不然你就要忍受不定时regionserver宕机的麻烦,而且集群恢复、移动region过程中,会造成集群整个的io负载严重,特别是当你的zookeeper和hbase部署在一起的时候,可能会因为io过高,导致zookeeper无法响应的情况,最终导致整个集群挂掉,这样的事情我遇到多次,希望大家引以为戒,尽量吧zookeeper进行单独部署。zookeeper的一些设置、优化可以参见:
2. HDFS客户端配置
如果你希望Hadoop集群上做HDFS 客户端配置 ,例如你的HDFS客户端的配置和服务端的不一样。按照如下的方法配置,HBase就能看到你的配置信息:
- 在hbase-env.sh里将
HBASE_CLASSPATH
环境变量加上HADOOP_CONF_DIR
。 - 在
${HBASE_HOME}/conf
下面加一个 hdfs-site.xml (或者 hadoop-site.xml) ,最好是软连接 - 如果你的HDFS客户端的配置不多的话,你可以把这些加到 hbase-site.xml上面.
例如HDFS的配置 dfs.replication
你希望复制5份,而不是默认的3份。如果你不照上面的做的话,Hbase只会复制3份。
3. 一些配置参数
以下参数来自apache的hbase版本,如果你使用的其他厂商的hbase,有可能默认值不一样。
-
zookeeper.session.timeout
:这个默认值是3分钟。这意味着一旦一个server宕掉了,Master至少需要3分钟才能察觉到宕机,开始恢复。你可能希望将这个超时调短,这样Master就能更快的察觉到了。在你调这个值之前,你需要确认你的JVM的GC参数,否则一个长时间的GC操作就可能导致超时。 -
hbase.regionserver.handler.count
:这个设置决定了处理用户请求的线程数量。默认是10,这个值设的比较小,主要是为了预防用户用一个比较大的写缓冲,然后还有很多客户端并发,这样region servers会垮掉。有经验的做法是,当请求内容很大(上MB,如大puts, 使用缓存的scans)的时候,把这个值放低。请求内容较小的时候(gets, 小puts, ICVs, deletes),把这个值放大。把这个值放大的危险之处在于,把所有的Put操作缓冲意味着对内存有很大的压力,甚至会导致OutOfMemory.一个运行在内存不足的机器的RegionServer会频繁的触发GC操作,渐渐就能感受到停顿。一段时间后,集群也会受到影响,因为所有的指向这个region的请求都会变慢。这样就会拖累集群,加剧了这个问题。 -
hbase.client.keyvalue.maxsize
:一个KeyValue实例的最大size。如果设置为0或者更小,就会禁用这个检查。默认10MB。 -
hbase.regionserver.lease.period
:户端租用HRegion server 期限,即超时阀值。单位是毫秒。默认情况下,客户端必须在这个时间内发一条信息,否则视为死掉。默认值为60000。 -
hbase.regionserver.msginterval
:RegionServer 发消息给 Master 时间间隔,单位是毫秒,默认: 3000 -
hbase.regionserver.optionallogflushinterval
:将Hlog同步到HDFS的间隔。如果Hlog没有积累到一定的数量,到了时间,也会触发同步。默认是1秒,单位毫秒。 -
hbase.regionserver.logroll.period
:提交commit log的间隔,不管有没有写足够的值。默认: 3600000 -
hbase.regionserver.thread.splitcompactcheckfrequency
:region server 多久执行一次split/compaction 检查。默认: 20000 -
hbase.balancer.period
:Master执行region balancer的间隔。默认: 300000 -
hbase.hregion.memstore.block.multiplier
:如果memstore有hbase.hregion.memstore.block.multiplier
倍数的hbase.hregion.flush.size
的大小,就会阻塞update操作。这是为了预防在update高峰期会导致的失控。如果不设上界,flush的时候会花很长的时间来合并或者分割,最坏的情况就是引发out of memory异常。默认: 2 -
hbase.hstore.compactionThreshold
:当一个HStore含有多于这个值的HStoreFiles(每一个memstore flush产生一个HStoreFile)的时候,会执行一个合并操作,把这HStoreFiles写成一个。这个值越大,需要合并的时间就越长。默认: 3 -
hbase.hstore.blockingStoreFiles
:当一个HStore含有多于这个值的HStoreFiles(每一个memstore flush产生一个HStoreFile)的时候,会执行一个合并操作,update会阻塞直到合并完成,直到超过了hbase.hstore.blockingWaitTime
的值。默认: 7
4. HBase 和 MapReduce
当 MapReduce job的HBase table 使用TableInputFormat为数据源格式的时候,他的splitter会给这个table的每个region一个map。因此,如果一个table有100个region,就有100个map-tasks,不论需要scan多少个column families 。
通常建议关掉针对HBase的MapReduce job的预测执行
(speculative execution)功能。这个功能也可以用每个Job的配置来完成。对于整个集群,使用预测执行意味着双倍的运算量。这可不是你所希望的,因此我们需要进行如下配置:
MapReduce任务的预测执行缺省是打开的,HBase集群一般建议在系统级关闭预测执行,除非在某种特殊情况下需要打开,此时可以每任务配置。设置mapred.map.tasks.speculative.execution 和 mapred.reduce.tasks.speculative.execution 为 false,可以在job执行的时候设置,也可以直接配置的集群中。
5.HBase 的 Schema 设计
flush和compaction操作是针对一个Region。
Compaction操作现在是根据一个column family下的全部文件的数量触发的,而不是根据文件大小触发的。当很多的column families在flush和compaction时,会造成很多没用的I/O负载(要想解决这个问题,需要将flush和compaction操作只针对一个column family)
行的版本的数量是HColumnDescriptor设置的,每个column family可以单独设置,默认是3。
6. 性能调优
1、长时间GC停顿
Hbase中常见的两种stop-the-world的GC操作:
- 一种是CMS失败的模式
- 另一种是老一代的堆碎片导致的
要想定位第一种,只要将CMS执行的时间提前就可以了,加入 -XX:CMSInitiatingOccupancyFraction
参数,把值调低。可以先从60%和70%开始(这个值调的越低,触发的GC次数就越多,消耗的CPU时间就越长)。要想定位第二种错误,Todd加入了一个实验性的功能,将你的Configuration中的 hbase.hregion.memstore.mslab.enabled
设置为true。
2、使用压缩
3、设置合理的版本
4、控制split和compaction