在HBase1.1.0发布之前,HBase同一集群上的用户、表都是平等的,没有优劣之分。这种’大同’社会看起来完美,实际上有很多问题。最棘手的主要有这么两个,其一是某些业务较其他业务重要,需要在资源有限的情况下优先保证核心重要业务的正常运行,其二是有些业务在某些场景下会时常’抽风’,QPS常常居高不下,严重消耗系统资源,导致其他业务无法正常运转。
  
  这实际上是典型的多租户问题,社区针对这个问题提出了相应的应对措施,主要有如下三点:
  
  (1)资源限制,主要针对用户、namespace以及表的QPS和请求大小进行限制,详见HBase-11598
  
  (2)资源调度,主要针对任务进行优先级调度,通常会优先调度实时交互而且小的任务,而批量操作任务或者长时间操作任务(大scan)优先级相对较低,详见HBase-10993
  
  (3)资源隔离,将不同表通过物理隔离的方式分布到不同的RegionServer上,详见HBase-6721
  
  本文将会重点介绍HBase中的资源限制方案 – Quotas,主要对其使用方式、实现原理进行介绍,并对其实际效果通过实践进行验证。另外,本文还会对HBase的资源调度原理进行简单介绍,并对主要配置进行讲解。
  
  资源限制-Quotas
  
  Quotas使用条件
  
  (1)HBase版本在1.1.0以上,或者低版本HBase应用了对应的Patch(HBase-11598)
  
  (2)Quotas功能默认是关闭的,需要在配置文件hbase-site.xml中通过设置hbase.quota.enabled为true打开。设置完成之后,需要重启HMaster才能生效。
  
  Quotas语句详解
  
  [java] view plain copy
  
  hbase> set_quota TYPE => THROTTLE, THROTTLE_TYPE => READ, USER => 'u1', TABLE => 't2', LIMIT => '10req/sec'
  
  (1)Quotas分别支持表级别以及用户级别资源限制,或者同时支持表级别和用户级别,如示例所示
  
  (2)THROTTLE_TYPE可以取值READ / WRITE,分别对随机读和随机写进行限制
  
  (3)LIMIT 可以从两个维度对资源进行限制,分别为req/time 和 size/time,前者限制单位时间内的请求数,后者限制单位时间内的请求数据量。需要指明的是time的单位可以是sec | min | hour | day,size的单位可以是B(bytes) | K | M | G | T | P,因此LIMIT可以表示为’1000req/min’或者’100G/day’,分别表示’限制1分钟的请求数在1000次以内’,’限制每天的数据量为100G’
  
  常用Quotas语句
  
  [sql] view plain copy
  
  hbase> set_quota TYPE => THROTTLE, TABLE => 't1', LIMIT => '1000req/sec'
  
  hbase> set_quota TYPE => THROTTLE, THROTTLE_TYPE => WRITE, USER => 'u1', LIMIT => '10M/sec'
  
  注意事项
  
  (1)set_quota命令执行的限制都是针对单个RegionServer来说的,并不是针对整个集群
  
  (2)set_quota命令默认执行后并不会立刻生效,需要等待一段时间才会生效,等待时间默认为5min。可以通过参数 hbase.quota.refresh.period 进行设置,比如可以通过设置
  
  hbase.quota.refresh.period = 60000将生效时间缩短为1min
  
  (3)可以通过命令list_quotas查看当前所有执行的set_quota命令
  
  Quotas – 实现原理
  
  原理很简单,如果请求数超过设置的Quota数,就抛出异常!有同学会说也没在日志中看到任何异常嘛,这是因为这类异常日志级别是debug,而默认的日志输出级别为info,可以通过调整log4j来查看。但是这类异常实在太多,没有必要输出。
  
  Quotas – 实践效果
  
  了解了Quotas的使用方法以及基本原理,是不是很想试一试它的功效,笔者在测试环境做了如下的测试:
  
  1. 测试硬件情况
  
  集群规模
  
  RS JVM内存配置
  
  硬盘
  
  HBase版本
  
  YCSB版本
  
  4台RegionServer
  
  72G
  
  12 * 3.6T
  
  1.1.2
  
  0.8.0
  
  2. 测试环境新建两张表,分别称为A和B。两张表的数据构成都相同,10亿条数据,每条数据500Bytes,总大小500G左右。
  
  3. 分别使用两个YCSB客户端分别对这两张表执行读写混合操作(读写比为1:1),再然后对B表不断执行set_quota操作,对该表QPS进行限制。再分别观察A表和B表的QPS以及读延迟变化情况。
  
  4. 为了方便理解,下面测试结果中A表称为Unthrottle_Table,B表称为Throttle_www.taohuayuan178.comTable。测试结果如下:
  
  通过测试基本可以看出,随着B表执行的QPS限制越来越严格,上图中Throttle_Table表对应的吞吐量(红色柱状图)越来越小,相应Unthrottle_Table表(紫色柱状图)对应的吞吐量却越来越大,这是因为B表执行QPS限制之后各种硬件资源就会更多地分配给A表。
  
  总体来说,Quotas功能总体看来基本完成了资源限制的职能,达到了资源限制的目的。同时支持用户级别和表级别,另外同时支持请求大小和请求数量两个维度,基本涵盖了常见的资源限制维度;另外,易用性也是一大亮点,比较人性化,只需要在Shell界面上敲一行命令就可以搞定。
  
  资源调度
  
  在 0.99版本之前,HBase只提供了一种请求队列类型:FIFO队列,意为先到的请求会优先被处理,后到的请求需要等待之前的请求被处理完。这样的设计有一个致命的缺陷,就是在线交互式查询有可能会被离线大scan长时间阻塞,而从优先级的角度讲在线交互式查询无疑更加重要。
  
  0.99版本之后,HBase将默认请求队列由FIFO类型改为了Deadline类型,用来解决上述缺陷。提起DeadLine队列,很多对Linux IO调度算法比较了解的同学并不陌生,Linux IO常用调度算法主要有Noop、CFQ(Completely Fair Queuing)以及Deadline,其中Noop调度算法基本可以认为就是FIFO算法,因此同样存在上述弊端;而CFQ算法会按照IO请求的地址进行排序,这样处理的目的在于尽量少地减少磁盘移动,实际效果来看确实极大的提升了IO的吞吐率,但是相比Noop,部分IO请求有可能会一直排到队尾,存在饿死的情况。Deadline算法首先将读写IO队列进行了分离,而且读IO优先级要高于写IO优先级;除此之外,它还会为每一个IO请求设置一个时间戳,用以判断请求是否长时间没有得到处理,进而需要优先处理。需要知道的是,对于常见数据库环境来说(Oracle,MySQL等www.567860.cn ),Deadline算法总是最佳选择。
  
  那HBase新增的Deadline算法和Linux IO中Deadline算法是否一样呢?答案是肯定的,至少两者实现思路基本是一致的。接下来主要结合HBase请求调度源码对Deadline算法进行深入分析。
  
  Deadline算法基于Deadline类型队列实现,Deadline类型队列和FIFO类型队列不同,属于优先级队列,里面的元素会按照优先级进行排序,优先级高的排在队首,优先级低的排在队尾。很显然,Deadline算法目标是使得在线交互式查询请求优先级更高,而离线长scan请求优先级更低。除此之外还有一个通常不会被注意的目标:不能出现任何请求被饿死!在弄懂具体的实现机制前,需要首先搞清楚一个问题:如何量化一个scan的请求长短?
  
  如何量化一个scan的请求长短:这个问题的理解需要对scan的流程有一个大体认识,一次scan请求并不会将所有数据查询返回,这一方面是因为在数据量大的场景下诸如带宽之类的系统资源会被严重消耗,另一方面也有可能会因为数据量大导致客户端OOM。因此HBase实际上将一次scan请求分为多次连续的next小请求执行,每次查询纪录数用户可以配置,默认为100条。这样假如一次scan查询总纪录数为1000,每次查询返回100条,就需要10次客户端到服务器端的next请求。看到这里,很多童鞋已经明白,可以通过当前RPC请求次数(即next RPC调用次数)粗略地衡量scan的长短,比如当前scanA的RPC请求次数为10,scanB的RPC请求次数为5,就可以认为scanA长于scanB,那理论上scanA的这次请求优先级就会低于scanB的这次请求。
  
  HBase在具体实现中会为每一个请求设置一个deadline(时间期限),代表这个请求的处理期限,deadline越小,请求优先级越高。
  
  这个deadline参数是理解HBase资源调度的关键,它由两部分构成:后半部分的核心在于vtime,代表当前scan的next请求次数,可见vtime越大(scan越长),对应的deadline越大,优先级越低;因为设定get操作的vtime为0,因此同等条件下get操作优先级最高;可见,通过vtime就可以实现请求优先级功能。那对于长scan,会不会出现因为优先级太低长时间得不到处理饿死的情况呢?这就需要看看前半部分,timestamp表示请求点的绝对时间戳,设置绝对时间戳是为了保证该请求的deadline肯定早于5s(等式后面部分最大就是5s)之后所有请求的deadline,从而能够保证不会被饿死;
  
  好吧,上面不是说Linux IO调度系统中Deadline算法还实现了读IO和写IO的分离,那HBase实现了么?当然,用户只需要通过简单的配置就不仅可以实现读请求和写请求的分离,还可以实现了scan请求的分离。
  
  默认场景下,HBase只提供一个队列,所有请求都会进入该队列进行优先级排序。用户可以通过设置参数hbase.ipc.server.callqueue.handler.factor www.thy157.com来设置多个队列,队列个数等于该参数 * handlercount,比如该参数设置为0.1,总的handlercount胃150,则会产生15个独立队列。
  
  独立队列产生之后,可以通过参数 hbase.ipc.server.callqueue.read.ratio 来设置读写队列比例,比如设置0.6,则表示会有9个队列用于接收读请求,6个用于接收写请求;另外,可以通过参数 hbase.ipc.www.huarenyl.cn server.callqueue.scan.ratio 设置get和scan的队列比例,比如设置为0.1,表示1个队列用于scan请求,另外8个用于get请求;
  
  总结
  
  本文主要介绍了HBase中多租户实现中的两个重要手段:资源限制以及资源调度,对其工作原理以及使用方法进行了解析。

HBase多租户机制分析的更多相关文章

  1. LevelDB Cache实现机制分析

    几天前淘宝量子恒道在博客上分析了HBase的Cache机制,本篇文章,结合LevelDB 1.7.0版本的源码,分析下LevelDB的Cache机制. 概述 LevelDB是Google开源的持久化K ...

  2. Linux mips64r2 PCI中断路由机制分析

    Linux mips64r2 PCI中断路由机制分析 本文主要分析mips64r2 PCI设备中断路由原理和irq号分配实现方法,并尝试回答如下问题: PCI设备驱动中断注册(request_irq) ...

  3. IOS Table中Cell的重用reuse机制分析

    IOS Table中Cell的重用reuse机制分析 技术交流新QQ群:414971585 创建UITableViewController子类的实例后,IDE生成的代码中有如下段落: - (UITab ...

  4. 您还有心跳吗?超时机制分析(java)

    注:本人是原作者,首发于并发编程网(您还有心跳吗?超时机制分析),此文结合那里的留言作了一些修改. 问题描述 在C/S模式中,有时我们会长时间保持一个连接,以避免频繁地建立连接,但同时,一般会有一个超 ...

  5. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  6. Linux信号(signal) 机制分析

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

  7. Java 动态代理机制分析及扩展

    Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...

  8. Android内存机制分析1——了解Android堆和栈

    //----------------------------------------------------------------------------------- Android内存机制分析1 ...

  9. memcache redundancy机制分析及思考

    设计和开发可以掌控客户端的分布式服务端程序是件幸事,可以把很多事情交给客户端来做,而且可以做的很优雅.角色决定命运,在互联网架构中,web server必须冲锋在前,注定要在多浏览器版本以及协议兼容性 ...

随机推荐

  1. js Date对象要注意的问题(时间转换)

    1.时间戳和时间对象可以灵活转变: let n = new Date() // 返回的是当前时间对应的国际时间 let nt =n.getTime() let n2 =new Date(nt) con ...

  2. DE1-SOC开发板使用学习

    1. Yocto build utility 工具是什么?Linux Console with framebuffer是什么? 2. 文档里面有几个Linux发布版本的,分别是ubuntu和LXDE版 ...

  3. JavaWeb(十三)——使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  4. TensorFlow深度学习实战---MNIST数字识别问题

    1.滑动平均模型: 用途:用于控制变量的更新幅度,使得模型在训练初期参数更新较快,在接近最优值处参数更新较慢,幅度较小 方式:主要通过不断更新衰减率来控制变量的更新幅度. 衰减率计算公式 : deca ...

  5. 测试面试必会sql(1)

    测试一般各种查询语句用的较多,下面的查询语句都是需要熟悉的 Course表 Score表 Student表 Teacher表 1,查询课程编号为“02”的总成绩 SELECT * FROM `Scor ...

  6. 第六篇 native 版本的Postman如何通过代理服务器录制Web及手机APP请求

    第四篇主要介绍了chrome app版本的postman如何安装及如何录制Web脚本,比较简单. 但是chrome app 版本和native 版本相比,对应chrome app 版本官方已经放弃支持 ...

  7. 初试Gevent – 高性能的Python并发框架

    Gevent是一个基于greenlet的Python的并发框架,以微线程greenlet为核心,使用了epoll事件监听机制以及诸多其他优化而变得高效. 于greenlet.eventlet相比,性能 ...

  8. 两张神图介绍python3和 2.x与 3.x 的区别

    有感与第一张图, 做了第二张图.

  9. python_MySQL 数据库操作

    Python中的mysql操作可以使用MySQLdb模块来完成.它符合Python社区设计的Python Database API SpecificationV2.0标准,所以与其他的数据库操作的AP ...

  10. Java接口interface,匿名内部类

    接口 1.接口内部为 常量+公用的抽象方法.类必须实现接口中的所有方法 2.接口的语法格式:不写abstract会自动添加,可以继承多个接口 修饰符不能使private,protected [修饰符] ...