背景
易扩展性,准确来说是易横向扩展性,一直是HBase引以为豪的优点之一,所以理论上HBase的集群规模可以做到很大,多个产品和业务的数据可以存在一个HBase中统一管理,节省运维资源和成本。
但是集群规模大了,数据量多了,处理负载变高了,加上各个产品和业务之间优先级不同,负载不同,对不同资源的敏感性也不同,使得简单粗暴的共用一个集群的效果并不是很好,面对这种业务场景早期的HBase版本并没有相关的解决方案,所以更多的就是各自为战,各自用各自的集群,这样不仅使得HBase集群重复建设,增加硬件投入以及运维成本外,更是埋没了HBase的易扩展型的特点,所以后续的HBase版本中慢慢加入了多租户以及业务资源隔离相关的解决方案。
正文
下面就从硬件资源隔离以及业务资源隔离两个方面来说明下HBase的实现:
硬件资源隔离--RsGroup
RsGroup概述
此功能用于将统一的大HBase 集群的 RegionServer 划分为多个分组,管理员可以将不同的表放入不同分组进行资源隔离,避免无关系的业务之间互相影响。
同样也可以根据不同的业务需求提供不同的硬件资源。对于于重点业务,可以分配更多的regionserver的机器,降低负载;而对于非重点业务,则可以更少的机器承担负更多的业务。
目前datanode已经支持了分级存储,甚至可以将重点业务使用不同的介质,比如SSD,从而达到硬件资源利用率和业务执行效率双提升的目的。
下图就是HBase中RsGroup的实现方式:
RsGroup特点
从上图以及上面的描述可以看出,RsGroup的特点如下:
优点
隔离级别做到RegionServer级别,即HBase层面的资源以及操作已经做到隔离,各个group之间不会相互影响
可以根据业务定制化硬件配给,提升硬件使用率
各个group之间隔离,保证了各个业务系统的稳定性
方便管理和扩展
提升了整个集群的性能
缺点
HBase底层的HDFS还是公用一份,如果HDFS出现问题,可能会影响一个甚至多个的RsGroup
RsGroup启用
启用过程修改所有节点的hbase-site.xml, 并重启master即可,配置修改如下:
<property> <name>hbase.coprocessor.master.classes</name> <value>org.apache.hadoop.hbase.rsgroup.RSGroupAdminEndpoint</value> </property> <property> <name>hbase.master.loadbalancer.class</name> <value>org.apache.hadoop.hbase.rsgroup.RSGroupBasedLoadBalancer</value> </property>
RsGroup原则
生产系统中的RsGroup的使用需要兼顾到很多硬件成本以及业务需求相关的限制,下面给出几个相对通用的原则供大家参考:
在线业务和离线业务尽量划分到不同组
重要业务和边缘业务尽量划分到不同组
非常重要的业务尽量单独划分到独立组或者单独部署集群
最好将系统表单独放在一个组中,防止业务数据影响HBase的正常使用
针对数据以及业务量较少的业务,单独创建组可能比较浪费,可以创建一个公共组来支撑此种场景
使用RSGroup会自动关闭全局自动负载均衡,后续需要手工触发
RsGroup管理
最后说说RsGroup使用过程中相关的管理以及注意事项:
开启完毕RsGroup并且table迁移过程中,需要注意RIT region的数量变化,可以通过hbase hbck或者hbase的web界面进行跟踪,遇到了region卡在RIT阶段的需要手动处理和解决,如果没有RIT的region后,执行hbase hbck查看hbase的状态,如果是OK的则table迁移完成
开启完毕RsGroup并且table迁移完毕后需要手动对每个table执行major_compact以使每个table达到本地化的效果
删除RsGroup之前需要将该group下的regionserver和table都移除掉
在RsGroup投入使用后,需要对每个Group,尤其是重要业务的Group使用监控以及告警软件或者脚本进行状态监控和跟踪,通过获取到的Group状态作为集群运维以及管理的依据,进行资源的增减以及group的管理,保证集群稳定高效的运行
业务资源隔离--读写分离
RegionServer 默认情况下只提供一个请求队列给所有业务使用,该队列处理所有的读写请求,导致部分延迟较高的请求影响其他对延迟敏感的业务,大量的写请求影响了读请求。针对这种情况,HBase 提供了读写队列隔离方案。
HBase 有四种典型的数据API操作类型,分别为 get、scan 和put、delete,其中 get 和 scan 属于 read 类型,put、delete属于write类型。默认场景下,HBase 只提供一个队列,所有请求都会进入该队列进行优先级排序。在一些场景下,我们要求这四种类型的访问尽可能的互相不影响,那么就需要在线上配置读写分离。
首先,我们可以根据HBase的业务特点,即读多写少还是写多读少来分配读写的比例:
HBase 中的相关配置如下:
<property> <name>hbase.ipc.server.callqueue.read.ratio</name> <value>0.5</value></property>
该值在HBase中默认为0,代表读写资源不分离。如果将 hbase.ipc.server.callqueue.read.ratio 设置为0.5,则表示有50%的线程数处理读请求,剩余50%用于接收写请求。如果读多写少,则将该值设置为0.5-1之间;如果写多读少,则将该值设置为0-0.5之间。
其次,在某些场景下,读操作scan以及get也需要进行隔离,HBase也同样提供scan以及get的比例:
HBase 中的相关配置如下:
<property> <name>hbase.ipc.server.callqueue.scan.ratio</name> <value>0.5</value></property>
该值在HBase中默认为0,代表scan和get资源不分离。如果将 hbase.ipc.server.callqueue.scan.ratio 设置为0.5,则代表在50%的读线程之中,再有50%的线程处理 scan,也就是全部线程的25%。如果scan多get少,则将该值设置为0.5-1之间;如果get多scan少,则将该值设置为0-0.5之间。
原文:https://juejin.cn/post/7096387635421118500