1. HBase Schema及Rowkey设计
HBase 在实际生产使用中,需要根据具体的业务使用场景,给出相匹配的Rowkey 设计及HBase表Schema 设计,提升HBase 的使用性能,同时避免出现热点瓶颈问题。
1.1 HBase 表Schema 设计原则
在HBase 中有许多不同的数据集,具有不同的访问Schema 级别和服务级别的期望,下面的设计法则只是概述:
- 目标 region 的大小介于10 到50 GB 之间。
- 单个单元格大小不要超过10 MB,如果使用MOB,则为50 MB。否则,请考虑将单元格数据存储在对象存储 中,并在HBase 中存储指向数据的指针。
- 典型的Schema 在每个表中有1 到3 个列族,强烈不建议超过3个。HBase 表不应该被设计成模拟RDBMS 表
- 对于具有1 或2 列族的表格,大约50-100 个region 数量比较合适。
- 尽可能短地保留列族名称。列族名称存储在每个值(忽略前缀编码)中。它们不应该像在典型的RDBMS 中一样具有自我记录和描述性。
- 如果正在存储基于时间的机器数据或日志记录信息,并且行密钥基于设备ID 或服务ID 加上时间,则最终可能会出现一种Schema,即旧数据区域在某个时间段之后永远不会有额外的写入操作。在这种情况下,最终会有少量活动region 和大量没有新写入的较旧region。对于这些情况,可以容忍更多region 域,因为资源消耗仅由活动region 驱动。
- 如果只有一个列族忙于写入,则只有该列族兼容内存。分配资源时请注意写入Schema。
- 使用合适的压缩,一般建议使用SNAPPY压缩方式。
1.2 HBase 表Rowkey 设计原则
HBase 中的行按行键及顺序排序。这种设计优化了扫描(scan),允许将相关的行或彼此靠近的行一起读取。但是,设计不佳的行键是热点的常见来源。当大量客户端通信访问集群中的一个节点或仅少数几个节点时,会发生热点。此客户端通信可能表示读取、写入或其他操作。客户端访问压倒负责托管该region 的单个机器,从而导致性能下降并可能导致region 不可用。这也会对由同一台RegionServer 托管的其他region 产生不利影响,因为该主机无法为请求的负载提供服务。设计数据访问Schema 以使集群得到充分和均匀利用是非常重要的。
为了防止热点 写入,合理设计rowkey,可以将数据读写压力分散到多个region 上,而不是一个region。以下描述了避免热点的一些常用技术,以及各自优缺点。
1). 加盐Salting
Salting 是指将随机数据添加到行键的开头。在这种情况下,Salting 是指为行键添加一个随机分配的前缀,以使它的排序方式与其他方式不同。所有可能前缀的数量对应于要分散数据的region 的数量。
如果有一些“热点”行键模式,反复出现在其他更均匀分布的行中,那么Salting 可能会有帮助。下面的例子说明了Salting 能在多个RegionServer 间分散负载,同时也说明了它在读操作时候的负面影响。
假设存在的行键列表,表按照每个字母对应一个region 进行分割。前缀'a'是一个区域,前缀'b'是另一个区域。在此表中,所有以'f'开头的行都在同一个区域中。本示例重点关注具有以下键的行:
foo0001
foo0002
foo0003
foo0004
现在,假设想将它们分散到不同的region 上,就需要用到四种不同的salts:a,b,c,d。在这种情况下,每种字母前缀都对应着不同的一个region。用上这些salts 后,便有了下面这样的行键。
由于现在想把它们分到四个独立的区域,理论上吞吐量会是之前写到同一region 的情况的吞吐量的四倍。
a-foo0003
b-foo0001
c-foo0004
d-foo0002
如果想新增一行,新增的一行会被随机指定四个可能的salt 值中的一个,并放在某条已存在的行的旁边。
a-foo0003
b-foo0001
c-foo0003
c-foo0004
d-foo0002
由于前缀的指派是随机的,因而如果想要按照字典顺序找到这些行,则需要做更多的工作。从这个角度上看,salting 增加了写操作的吞吐量,却也增大了读操作的开销。
2). 哈希Hashing
可用一个单向的hash 散列来取代随机指派前缀。这样能使一个给定的行在“salted”时有相同的前缀,从某种程度上说,这在分散了RegionServer 间的负载的同时,也允许在读操作时能够预测。确定性hash(deterministic hash)能让客户端重建完整的行键,以及像正常的一样用Get 操作重
新获得想要的行。
考虑和上述salting 一样的情景,现在可以用单向hash 来得到行键foo0003,并可预测得‘a’这个前缀。然后为了重新获得这一行,需要先知道它的键。可以进一步优化这一方法,如让特定的键对总是在相同的region 上。
3). Reversing the Key(反转键)
通过反转一段固定长度或者可数的键,来让最常改变的部分(最低显著位,the least significant digit)在第一位,这样有效地打乱了行键,但是却牺牲了行排序的属性。
2. 调优
2.1 组件端调优
可以通过修改hbase-site.xml 中的配置调节HBase 性能,部分配置如表1 所示。
参数名 | 参数说明 |
hbase.regionserver.handler.count | 该设置决定了处理RPC的线程数量,通常可以调大。当请求内容很大的时候,如果该值设置过大则会占用过多内存,导致频繁GC,或者出现OutOfMemory |
hbase.hregion.memstore.flush.size | memstore的大小,超过该值数据将被flush到HDFS,默认128M,单位字节 |
hbase.hregion.memstore.block.multiplier | 默认值4,如果memstore的内存大小已经超过了 hbase.hregion.memstore.flush.size的4倍,则会阻塞memstore的写操作,直至降至hbase.hregion.memstore.flush.size以下。为避免阻塞,可适当调整该值 |
hbase.hstore.compactionThreshold | HStroe的storeFile数量大于该值时,则可能会进行compact。可以适当调大,减少compact的次数 |
hbase.client.scanner.caching | HBase scan缓存大小。应该根据业务特征配置,如果一行数据太 大,则应该设置一个较小的值,如果一行数据很小,则可以设置一个较大的值 |
2.2 其它调优
1). 建议rowkey 和列族名称越短越好
每个cell 值均会存储一次rowkey 和列族名称,rowkey 和列族名称越长,占用的存储空间越大,这样会极大影响HFile 的存储效率。
2). rowkey 遵循散列原则
HBase 中的行是按照rowkey 的字典顺序排序的,这种设计优化了scan 操作,但是当数据集中到少数的region,大量的访问会导致单个region 超出自身承受能力,引起性能下降甚至region 不可用。所以建议rowkey 使用散列字段,使数据均衡分布在RegionServer 上。
3). 列族越少越好
HBase 目前不能较好的处理两列族或三列族以上的业务应用,因此请将hbase 表schem 设计中的列族数量保持在较低水平。
目前,flushing 和compactions 是按照每个region 进行的,所以当一个列族操作大量数据的时候会引发一个flush。那些邻近的列族也有进行flush 操作,尽管它们没有操作多少数据。当许多列族存在时,flushing 和compactions 相互作用可能会导致一堆不必要的I/O(要通过更改flushing 和compactions 来针对每个列族解决该问题)。
列族是一个集中的存储单元,将具有相同IO 特性的列放在一个列族中会更高效,并且过多的列族会相互影响,影响HBase 的效率。
3. 常见问题
3.1日志查看方法
1). 日志所在路径
HBase 集群日志默认路径在/var/log/hbase。
2). 日志查看注意点
先通过HBase Web UI 或DataEngine 管理页面找出有问题的HBase 节点,如果为HBase Master问题,则找到HBase Master 节点日志,在日志中寻找报错信息(搜索关键字:Exception、ERROR),根据报错信息分析出错原因,找到对应的处理方法。如果为HBase Regionserver 问题,则找到HBase Regionserver 节点日志,在日志中寻找报错信息(搜索关键字:Exception、ERROR),根据报错信息分析出错原因,找到对应的处理方法。
对于现场无法定位问题,需要将问题节点日志及相关Master 相关日志发给技术服务人员进行问题定位解决。
3). 常见问题分析方法
首先需要通过HBase 的监控管理页面定位HBase 出问题原因点,然后根据日志进行分析,找出问题精确原因,通过源码分析、网络搜索、社区问题单跟踪等寻求解决方法解决问题。
3.2 常见问题
1). HBase 时钟不同步问题造成HBase 进程异常退出
报错异常信息:
org.apache.hadoop.hbase.ClockOutOfSyncException: Server slave1,16020,1494163890158 has
been rejected; Reported time is too far out of sync with master. Time difference of 52782ms >
max allowed of 30000ms
报错原因:报错节点与HBase Master 节点时间差超过配置时间。
解决方案:
a. 检查时钟同步服务是否开启,若未开启或安装,进行相应开启或安装操作。
b. 进行报错节点与HMaster 节点手动时钟同步。
2). org.apache.hadoop.hbase.security.AccessDeniedException 权限拒绝异常
访问HBase 进行表创建、数据读取等,由于没有权限,会报该错。例如创建表没有权限,报错信息如下所示:
org.apache.hadoop.hbase.security.AccessDeniedException:
org.apache.hadoop.hbase.security.AccessDeniedException: Insufficient permissions for user
'mingtong' (action=create)
at
org.apache.ranger.authorization.hbase.AuthorizationSession.publishResults(AuthorizationS
ession.java:261)
at
org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor.authorizeAccess(Ran
gerAuthorizationCoprocessor.java:595)
at
org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor.requirePermission(R
angerAuthorizationCoprocessor.java:664)
5-5
at
org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor.preCreateTable(Rang
erAuthorizationCoprocessor.java:769)
at
org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor.preCreateTable(Rang
erAuthorizationCoprocessor.java:496)
at
org.apache.hadoop.hbase.master.MasterCoprocessorHost$11.call(MasterCoprocessorHost.java:
222)
at
org.apache.hadoop.hbase.master.MasterCoprocessorHost.execOperation(MasterCoprocessorHost
.java:1146)
at
org.apache.hadoop.hbase.master.MasterCoprocessorHost.preCreateTable(MasterCoprocessorHos
t.java:218)
at org.apache.hadoop.hbase.master.HMaster.createTable(HMaster.java:1603)
at
org.apache.hadoop.hbase.master.MasterRpcServices.createTable(MasterRpcServices.java:462)
at
org.apache.hadoop.hbase.protobuf.generated.MasterProtos$MasterService$2.callBlockingMeth
od(MasterProtos.java:57204)
at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2127)
at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:107)
at org.apache.hadoop.hbase.ipc.RpcExecutor.consumerLoop(RpcExecutor.java:133)
at org.apache.hadoop.hbase.ipc.RpcExecutor$1.run(RpcExecutor.java:108)
at java.lang.Thread.run(Thread.java:748)
at sun.reflect.GeneratedConstructorAccessor15.newInstance(Unknown Source)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorI
mpl.java:45)
报错原因:用户无访问权限。
解决方案:
a. 根据报错原因,分析应该解决的权限问题,对于HBase 表或命名空间权限问题,使用对应的权限用户(表/命名空间的创建用户,系统表、hbase 及default 命名空间默认为hbase 用户),及“grant”授权命令进行赋权操作,进行问题解决。
b. 对于HBase 作业类操作,分析是HBase 表权限或命名空间权限问题,还是HDFS 权限问题,若为HBase 权限相关问题,使用上一步解决方法进行解决,若为HDFS 问题,使用hdfs chmod命令修改文件目录的权限。
3). 运行hbase shell 输入list 等基本语句报错
报错异常信息如下:
ERROR: Can't get master address from ZooKeeper; znode data == nullHere is some help for this
command:List all tables in hbase. Optional regular expression parameter could
be used to filter the output. Examples:
hbase> list
hbase> list 'abc.*'
hbase> list 'ns:abc.*'
hbase> list 'ns:.*'
报错原因:
a. 时间不同步,HBase 集群时间不同步可能会导致各种问题。
b. hbase-site.xml 里面的hbase.rootdir 与core-site.xml 中的fs.defaultFS 路径中配置的主机名或端口号不一致。
解决方案:
a. 查看集群各节点时钟同步服务进程状态及时间,并进行时间同步操作。
b. 查看报错原因2 中路径及端口是否一致。
c. 不是上述原因造成的话,可查找集群日志报错信息,寻求对应的解决方法。
4. client.HConnectionManager$HConnectionImplementation: Can”t get connection to ZooKeeper:KeeperErrorCode = ConnectionLoss for /hbase
报错原因:未关闭防火墙
解决方案:关闭防火墙
下面以CentOS 7 为例关闭防火墙,方法如下所示:
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall 开机启动
firewall-cmd -state #查看默认防火墙状态(关闭后显示notrunning,开启后显示running)
5). The table xxx does not exist in meta but has a znode. run hbck to fix inconsistencies.
报错原因:HBase 表xxx 的表描述相关信息在hbase:meta 表不存在,但在Zookeeper 中存在该HBase 表信息。
解决方案:以table hbasetest 为例
a. 执行hbase zkcli 命令进入zookeeper client 模式
b. ls /hbase/table 命令查看是否有hbasetest 这个表
c. 使用rmr /hbase/table/hbasetest 命令删除表
d. 重启Hbase
6). org.apache.hadoop.hbase.IPc.ServerNotRunningYetException: Server is not running yet
报错原因:Hadoop 处于safe mode
解决方案:
a. 查看hadoop 当前启动状态是否为safe mode
hadoop dfsadmin -safemode get
b.退出安全模式
hadoop dfsadmin -safemode leave
7). 磁盘故障,RegionServer 重启之后,Region offline
可能原因:磁盘故障,在Region 重新分配过程中,被分配的RegionServer 重启,Region 分配失败,Region offline。具体原因需结合排查磁盘故障原因,以及RegionServer 被重启的原因进行分析。
解决方案:排除故障原因,恢复磁盘故障。当磁盘故障恢复,HBase 健康状态恢复,执行hbase hbck-fixAssignments 使Region 恢复上线。
8). 查看HBase 组件日志,发现连接Zookeeper 组件失败,若定位HBase 组件没有问题,可能是
Zookeeper 服务存在问题
可能原因:Zookeeper 比较常见的问题就是因其数据存储目录空间不足,导致Zookeeper Server不能够正常提供服务,从而导致其他依赖于Zookeeper 的服务如HBase 组件连接Zookeeper 失败。
解决办法:查看Zookeeper 的数据存储目录所在的分区,清理该分区内无用的文件,释放空间,然
后重启Zookeeper 服务即可。