HBase-02运维和部署

安装 & 部署

为了保证 Region Server 读写性能,需要和 HDFS 的 NameNode 部署在同一台机器上,实现数据的本地性

  • Hadoop & HBase
    • Hadoop集群: 1x NameNode, 2x DataNode, 共7T
    • HBase集群: 1x Master, 2x RegionServer
  • 服务分布情况:
    • ip6 : hbase master, hadoop name_node, Zookeeper
    • ip7 : hbase region
    • ip8 : hbase region

hadoop

ssh ip6, 执行:

cd /data1 && mkdir -p hadoop/tmp && mkdir -p hadoop/hdf/data && mkdir -p hadoop/hdf/name

编辑 /etc/profile:

export HADOOP_HOME=/data0/hadoop-2.8.3
export PATH=$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH
export HADOOP_LOG_DIR=$HADOOP_HOME/logs
export YARN_LOG_DIR=$HADOOP_LOG_DIR

并执行 source /etc/profile

停止:

cd /data0/hbase-1.3.2/bin && sh stop-hbase.sh
cd /data0/hadoop-2.8.3/sbin && sh stop-dfs.sh && sh stop-yarn.sh

启动:

cd /data0/hadoop-2.8.3/sbin && start-dfs.sh && start-yarn.sh
cd /data0/hbase-1.3.2/bin && start-hbase.sh

zk

touch /data1/zookeeper/myid && echo 1 > /data1/zookeeper/myid
/data0/zookeeper-3.4.12/bin/zkServer.sh start

性能优化

① Server端优化:

  • JVM 内存优化: export HBASE_REGIONSERVER_OPT="-Xmx8g -Xms8g -Xmn128m -XX:+UseParNewGC -XX:UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -verbose:gc -XX:+printGCDetails -XX:+PrintGCTimeStamps -Xloggc:${HBASE_HOME}/logs/gc-${hostname}-hbase.log"

  • 使用压缩: GZIP, LZO, Zippy/Snappy, 创建表的时候指定列族的压缩格式:create 'testtable',{NAME => 'colfam1',COMPRESSION => 'GZ'}

  • 预分 Region: 在建表的时候预先创建多个 Region, 并规定好每个 Region 存储的 Rowkey 范围, 通过对数据的特性进行分析预先创建分区可以有效的解决 HBase 中的数据倾斜问题 @ref: HBase-03架构和原理

  • 防止拆分风暴:

    • Hbase 自动处理 region 拆分,一旦达到阀值 region 将会拆分成两个。当用户的 region 大小以恒定的速度保持增长时,region 拆分会在同一时间发生,因为同时需要压缩 region 中的存储文件,这个过程或重写拆分后的 region,导致磁盘 IO 上升。这种情况被称为拆分风暴
    • 如何防止:与其依赖 HBase 的自动拆分,还不如手动使用 split 和 major_compact 命令来管理,因为手动管理的话可以将这些 region 的拆分/ HFile 的合并时机分割开来,尽量分散 IO 负载。可以设置 hbase.hregion.max.filesize 为非常大,避免触发自动拆分的阈值。
  • region 热点问题: 通过合理设计 row key 解决; @ref: HBase-04行键设计

② 客户端API优化:

  • 禁用自动刷写 Table.setAutoFlush(false)

最佳实践-集群规划

  • 一个 HBase 集群上,如果给多个业务方使用,如何做业务之间的隔离?
  • 共享情况下如何使得系统资源利用率最高,理想情况下当然希望集群中所有软硬件资源都得到最大程度利用。

使得集群系统资源最大化利用,那首先要看业务对系统资源的需求情况。经过对线上业务的梳理,通常可将这些业务分为如下几类:

  1. 硬盘容量敏感型业务:这类业务对读写延迟以及吞吐量都没有很大的要求,唯一的需要就是硬盘容量。比如大多数离线读写分析业务,上层应用一般每隔一段时间批量写入大量数据,然后读取也是定期批量读取大量数据。特点:离线写、离线读,需求硬盘容量

  2. 带宽敏感型业务:这类业务大多数写入吞吐量很大,但对读取吞吐量没有什么要求。比如日志实时存储业务,上层应用通过kafka将海量日志实时传输过来,要求能够实时写入,而读取场景一般是离线分析或者在上次业务遇到异常的时候对日志进行检索。特点:在线写、离线读,需求带宽

  3. IO 敏感型业务:相比前面两类业务来说,IO 敏感型业务一般都是较为核心的业务。这类业务对读写延迟要求较高,尤其对于读取延迟通常在100ms 以内,部分业务可能要求更高。比如在线消息存储系统、历史订单系统、实时推荐系统等。特点:在(离)线写、在线读,需求内存、高 IOPS 介质

每个季度公司都会要求采购新机器,一般情况下机器的规格(硬盘总容量、内存大小、CPU规格)都是固定的。假如现在一台RegionServer的硬盘规格是3.6T x 12,总内存大小为128G,从理论上来说这样的配置是否会有资源浪费?如果有的话是硬盘浪费还是内存浪费?那合理的硬盘/内存搭配应该是什么样?

这里需要提出一个 Disk / Java Heap Ratio 的概念,即一台 RegionServer “磁盘容量 / JVM 内存” 的比值,这个比值多少最合理? 在给出合理的解释在前,先把结果给出来:

Disk Size / Java Heap = RegionSize / (MemstoreSize * ReplicationFactor * HeapFractionForMemstore * 2)

按照默认配置:
RegionSize = 10G,对应参数为 hbase.hregion.max.filesize
MemstoreSize = 128M,对应参数为 hbase.hregion.memstore.flush.size
ReplicationFactor = 3,对应参数为 dfs.replication
HeapFractionForMemstore = 0.4,对应参数为 hbase.regionserver.global.memstore.lowerLimit

计算为:10G / 128M * 3 * 0.4 * 2 = 192,意思是说一台 RegionServer 上1bytes 的 Java 内存大小需要搭配192bytes 的硬盘大小最合理,再回到之前给出的问题,128G 的内存总大小,拿出96G 作为 Java 内存用于 RegionServer,那对应需要搭配 96G * 192 = 18T 硬盘容量,而实际采购机器配置的是36T,说明在默认配置条件下会有几乎一半硬盘被浪费。

@ref: HBase最佳实践-集群规划 – 有态度的HBase/Spark/BigData

最佳实践-内存规划

@ref:: HBase最佳实践-内存规划 – 有态度的HBase/Spark/BigData

最佳实践-读性能优化

HBase最佳实践-读性能优化策略 – 有态度的HBase/Spark/BigData

最佳实践-写性能优化

  • 是否需要 WAL? WAL 是否需要同步写入?
  • Put 批量提交
  • Region 写入负载是否均衡
  • Key 大小

HBase最佳实践-写性能优化策略 – 有态度的HBase/Spark/BigData