平台篇-58 HBase 平台实践和应用

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 MongoDB,通用型 2核4GB
简介: HBase 是一个基于 Hadoop 的分布式、面向列的 Key-Value 存储系统,可以对需 要实时读写、随机访问大规模数据集的场景提供高可靠、高性能的服务,在大数 据相关领域应用广泛。HBase 可以对数据进行透明的切分,使得存储和计算本身 具有良好的水平扩展性。

HBase 是一个基于 Hadoop 的分布式、面向列的 Key-Value 存储系统,可以对需 要实时读写、随机访问大规模数据集的场景提供高可靠、高性能的服务,在大数 据相关领域应用广泛。HBase 可以对数据进行透明的切分,使得存储和计算本身 具有良好的水平扩展性。
在 58 的业务场景中,HBase 扮演重要角色。例如帖子信息等公司基础数据都是 通过 HBase 进行离线存储,并为各个业务线提供随机查询及更深层次的数据分 析。同时 HBase 在 58 还大量用于用户画像、搜索、推荐、时序数据和图数据等 场景的存储和查询分析。

HBase 在 58 的应用架构:
_2019_01_14_10_56_13
**
HBase 在 58 的应用架构如上图所示,主要内容包括以下几个部分:**

  1. 多租户支持:包括 SCF 限流、RSGroup、RPC 读写分离、HBase Quota 、ACL;
  2. 数据读写接口:包括 SCF 代理 API、原生 Java API 以及跨语言访问 Thrift Server;
  3. HBase 数据导入导出:包括数据批量导入工具 BulkLoad,数据批量导出工具
    SnapshotMR;
  4. OLAP:多维分析查询的 Kylin 平台;
  5. 时序数据库:时序数据存储和查询的时序数据库 Opentsdb;
  6. 图数据库:图关系数据存储和查询的图数据库 JanusGraph;
  7. SQL on HBase:支持二级索引和事务的 Phoenix,以及 Spark SQL 等;
  8. HBase 在 58 的应用业务场景包括:全量帖子数据、用户画像、搜索、推荐、
    用户行为、智能监控以及风控反欺诈等的数据存储和分析;
  9. 监控平台:HBase 平台的监控实现。

本文将从多租户支持、数据读写接口、数据导入导出和平台优化四个方面来重点 讲解 58HBase 平台的建设。
说明:下文中所有涉及到 RegionServer 的地方统一使用 RS 来代替。

1. HBase 多租户支持

HBase 在 1.1.0 版本之前没有多租户的概念,同一个集群上所有用户、表都是同 等的,导致各个业务之间干扰比较大,特别是某些重要业务,需要在资源有限的 情况下保证优先正常运行,但是在之前的版本中是无法保证的。从 HBase 1.1.0 开始,HBase 的多租户特性逐渐得到支持,我们的 HBase 版本是 1.0.0-cdh5.4.4, 该版本已经集成了多租户特性。

以下是 58 用户访问 HBase 的流程图:
_2019_01_14_10_58_41

我们从多个层面对 HBase 多租户进行了支持,主要分为以下两个大的方面:

  1. 资源限制:
    a) SCF Quota;

b) HBase Quota。

  1. 资源隔离:
    a) RS RPC 读写分离;

b) HBase ACL 权限隔离;
c) RSGroup 物理隔离。

**1.1 资源限制
(1)SCF Quota**
SCF 是公司自研的 RPC 框架,我们基于 SCF 封装了原生 HBase API,用户根据应 用需要申请 HBase SCF 服务调用时,需要根据应用实际情况填写 HBase 的每分 钟调用量(请求次数),在调用量超限时,SCF 管理平台可以实现应用级的限流, 这是全局限流。缺点是只能对调用量进行限制,无法对读写数据量大小限制。

以下是用户申请 HBase SCF 服务调用时需要填写的调用量:
_2019_01_14_10_59_55

(2)HBase Quota
HBase 的 Quota 功能可以实现对用户级、表级和命名空间级的资源进行限制。这 里的资源包括请求数据量大小、请求次数两个维度,这两个维度基本涵盖了常见 的资源限制。目前 HBase 的 Quota 功能只能限制到 RS 这一级,不是针对整个集 群的。但是因为可以对请求的数据量大小进行限制,一定程度上可以弥补了 SCF Proxy 应用级限流只能对请求次数进行限制的不足。

开启 Quota 的配置如下:
_2019_01_14_11_05_30

在开启了 HBase 的 Quota 后,Quota 相关的元数据会存储到 HBase 的系统表 hbase:quota 中。

在我们的 HBase 集群中之前遇到过个别用户读写数据量过大导致 RS 节点带宽被 打满,甚至触发 RS 的 FGC,导致服务不稳定,影响到了其他的业务,但是应用级的调用量并没有超过申请 SCF 时设置的值,这个时候我们就可以通过设置 HBase Quota,限制读写表级数据量大小来解决这个问题。

以下是设置 HBase Quota 信息,可以通过命令行进行设置和查看:
_2019_01_14_11_06_29

1.2 资源隔离

(1)RS RPC 读写分离
默认场景下,HBase 只提供一个 RPC 请求队列,所有请求都会进入该队列进行 优先级排序。这样可能会出现由于读问题阻塞所有 handler 线程导致写数据失败, 或者由于写问题阻塞所有 handler 线程导致读数据失败,这两种问题我们都遇到过,在后续篇幅中会提到,这里不细述。

通过设置参数 hbase.ipc.server.callqueue.handler.factor 来设置多个队列,队列个数等于该参数 * handler 线程数,比如该参数设置为 0.1,总的 handler 线程数为200,则会产生 20 个独立队列。 独立队列产生之后,可以通过参数 hbase.ipc.server.callqueue.read.ratio 来设置读写队列比例,比如设置 0.6,则表示会有 12 个队列用于接收读请求,8 个用于接收写请求;另外,还可以进一步 通过参数 hbase.ipc.server.callqueue.scan.ratio 设置 get 和 scan 的队列比例,比 如设置为 0.2,表示 2 个队列用于 scan 请求,另外 10 个用于 get 请求,进一步还将 get 和 scan 请求分开。

RPC 读写分离设计思想总体来说实现了读写请求队列资源的隔离,达到读写互不干扰的目的,根据 HBase 集群服务的业务类型,我们还可以进一步配置长时 scan 读和短时 get 读之间的队列隔离,实现长时读任务和短时读任务互不干扰。

(2)HBase ACL 权限隔离

HBase 集群多租户需要关注的一个核心问题是数据访问权限的问题,对于一些重 要的公共数据,或者要进行跨部门访问数据,我们只开放给经过权限申请的用户 访问,没有权限的用户是不能访问的,这就涉及到了 HBase 的数据权限隔离了, HBase 是通过 ACL 来实现权限隔离的。
基于 58 的实际应用情况,访问 HBase 的用户都是 Hadoop 计算集群的用户,而 且 Hadoop 用户是按部门分配的,所以 HBase 的用户也是到部门而不是到个人, 这样的好处是维护的用户数少了,便于管理,缺点是有的部门下面不同子部门之 间如果也要进行数据权限隔离就比较麻烦,需要单独申请开通子部门账号。

要开启 HBase 的 ACL,只需要在配置文件 hbase-site.xml 中关于 Master、 RegionServer 和 Region 的协处理器都加上 org.apache.hadoop.hbase.security.access.AccessController 类就可以了。

具体 HBase ACL 的配置项如下图所示:
_2019_01_14_11_12_22

HBase 的访问级别有读取(R)、写入(W)、执行(X)、创建(C)、管理员(A),而权限作 用域包括超级用户、全局、命名空间、表、列族、列。访问级别和作用域的组合 创建了可授予用户的可能访问级别的矩阵。在生产环境中,根据执行特定工作所 需的内容来考虑访问级别和作用域。
在 58 的实际应用中,我们将用户和 HBase 的命名空间一一对应,创建新用户时, 创建同名的命名空间,并赋予该用户对同名命名空间的所有权限(RWCA)。以下 以新用户 zhangsan 为例,创建同名命名空间并授权:

_2019_01_14_11_13_38

(3)RSGroup 物理隔离

虽然 SCF Quota 和 HBase Quota 功能可以做到对用户的读写进行限制,一定程度上能降低各业务读写数据的相互干扰,但是在我们的实际业务场景中,存在两类特殊业务,一类是消耗资源非常大,但是不希望被限流,另外一类是非常重要, 需要高优先级保证服务的稳定。对于这两种情况下,我们只能对该业务进行物理隔离,物理隔离既能保证重要业务的稳定性,也避免了对其他业务的干扰。我们使用的物理隔离方案是 RSGroup,也即 RegionServer Group。

RSGroup 整体架构:
_2019_01_14_11_14_32

RSGroup 有以下几个特点:

  1. 不同 RS 和表划分到不同的 RSGroup;
  2. 同一个 RS 只能属于一个 RSGroup;
  3. 同一个表也只能属于一个 RSGroup;
  4. 默认所有 RS 和表都属于“default”这个 RSGroup。

RSGroup 实现细节:
_2019_01_14_11_15_44

从以上 RSGroup 实现细节中看出,RSGroup 的功能主要包含两部分,RSGroup 元数据管理以及 Balance。

RSGroup 开启的配置项:
_2019_01_14_11_16_24

  1. 数据读写接口
    目前我们提供了三种 HBase 的数据读写接口以便于用户使用,包括 SCF 代理、 Java 原生 API 和 Thrift Server。以下分别进行说明:

2.1 SCF Proxy

SCF 是 58 架构部自研的 RPC 框架,我们基于 SCF 封装了原生的 Java API,以 SCF RPC 接口的方式暴露给用户使用,其中以这种方式提供给用户的接口多达 30 个。 由于 SCF 支持跨语言访问,很好的解决了使用非 Java 语言用户想要访问 HBase 数据的问题,目前用户使用最多的是通过 Java、Python 和 PHP 这三种语言来访问这些封装的接口。

SCF proxy 接口整体架构:
_2019_01_14_11_40_52

数据读写流程:用户通过 RPC 连接到 SCF 服务管理平台,通过 SCF 服务管理平 台做服务发现,找到 58 云计算平台上部署的服务节点,服务节点最终通过访问 HBase 实现用户数据的读写操作。

使用 SCF Proxy 接口的优势:

  1. 避免用户直连 HBase 集群,降低 zk 的压力。之前经常遇到因为用户代码存 在 bug,导致 zk 连接数暴涨的情况。
  2. 针对大量一次性扫描数据的场景,提供单独访问接口,并在接口中设置 scan 的 blockcache 熟悉为 false,避免了对后端读缓存的干扰。
  3. 通过服务管理平台的服务发现和服务治理能力,结合业务的增长情况以及基 于 58 云计算平台弹性特点,我们很容易对服务节点做自动扩容,而这一切对用户是透明的。
  4. 通过服务管理平台可以实现对用户的访问做应用级限流,规范用户的读写操作。
  5. 服务管理平台提供了调用量、查询耗时以及异常情况等丰富的图表,用户可以很方便查看。

以下是我们的 SCF 服务在服务管理平台展示的调用量和查询耗时图表:
_2019_01_14_11_41_50

由于 SCF Proxy 接口的诸多优势,我们对于新接的业务都要求通过申请这种方式 来访问 HBase。

2.2 Java API

由于历史原因和个别特殊的新业务还采用 Java 原生的 API 外,其他新业务都通 SCF Proxy 接口来访问。
**
2.3 Thrift Server**

也是由于历史原因,个别用户想使用非 Java 语言来访问 HBase,才启用了 Thrift Server,由于 SCF proxy 接口支持多语言,目前这种跨语言访问的问题都通过 SCF Proxy 来解决了。

3. 数据导入导出 3.1 BulkLoad

3.1 BulkLoad

HBase 相对于其他 KV 存储系统来说比较大的一个优势是提供了强大的批量导入 工具 BulkLoad,通过 BulkLoad,我们很容易将生成好的几百 G,甚至上 T 的 HFile 文件以毫秒级的速度导入 HBase,并能马上进行查询。所以对于历史数据和非实 时写入的数据,我们会建议用户通过 BulkLoad 的方式导入数据。

3.2 SnapshotScanMR

针对全表扫描的应用场景,HBase 提供了两种解决方案,一种是 TableScanMR, 另一种就是 SnapshotScanMR,这两种方案都是采用 MR 来并行化对数据进行扫描,但是底层实现原理确是有很大差别,以下会进行对比分析。

TableScanMR 的实现原理图:
_2019_01_14_11_47_16

TableScanMR 会将 scan 请求根据 HBase 表的 region 分界进行分解,分解成多个 sub-scan(一个 sub-scan 对应一个 map 任务),每个 sub-scan 内部本质上就是一个 ScanAPI。假如 scan 是全表扫描,那这张表有多少 region,就会将这个 scan 分解成多个 sub-scan,每个 sub-scan 的 startkey 和 stopkey 就是 region 的 startkey 和 stopkey。这种方式只是简单的将 scan 操作并行化了,数据读取链路 和直接 scan 没有本质区别,都需要通过 RS 来读取数据。
SnapshotScanMR 的实现原理图:

_2019_01_14_11_47_53

SnapshotScanMR 总体来看和 TableScanMR 工作流程基本一致,不过 SnapshotScanMR 的实现依赖于 HBase 的 snapshot,通过 shapshot 的元数据信息,SnapshotScanMR 可以很容易知道当前全表扫描要访问那些 HFile以及这些 HFile 的 HDFS 路径,所以 SnapshotScanMR 构造的 sub-scan 可以绕过 RS,直接 借用 Region 中的扫描机制直接扫描 HDFS 中数据。

SnapshotScanMR 优势:

  1. 避免对其他业务的干扰:SnapshotScanMR 绕过了 RS,避免了全表扫描对其 他业务的干扰。
  2. 极大的提升了扫描效率:SnapshotScanMR 绕过了 RS,减少了一次网络传输, 对应少了一次数据的序列化和反序列化操作;TableScanMR 扫描中 RS 很可 能会成为瓶颈,而 SnapshotScanMR 不需要担心这一点。

基于以上的原因,在全部扫描,以及全部数据导出的应用场景中,我们选择了 SnapshotScanMR,并对原生的 SnapshotScanMR 进行了进一步的封装,作为一个通用工具提供给用户。

4. 平台优化

在使用 HBase 的过程中,我们遇到了很多问题和挑战,但最终都一一克服了,以下是我们遇到一部分典型问题及优化:

4.1 CLOSE_WAIT 偏高优化

问题描述:在一次排查 HBase 问题的时候发现 RS 进程存在大量的 CLOSE_WAIT, 最多的达到了 6000+,这个问题虽然还没有直接导致 RS 挂掉,但是也确实是个 不小的隐患。

从 socket 的角度分析产生 CLOSE_WAIT 的原因:对方主动关闭连接或者网络异 常导致连接中断,这时我方的状态会变成 CLOSE_WAIT, 此时我方要调用 close() 来使得连接正确关闭,否则 CLOSE_WAIT 会一直存在。

对应到咱们这个问题,其实就是用户通过 RS 访问 DataNode(端口 50010)的数 据,DataNode 端已经主动关闭 Socket 了,但是 RS 端没有关闭,所以要解决的 问题就是 RS 关闭 Socket 连接的问题。

解决办法:社区对该问题的讨论见 HBASE-9393。该问题的修复依赖 HDFS-7694, 我们的 Hadoop 版本是 hadoop2.6.0-cdh5.4.4,已经集成了 HDFS-7694 的内容。

HBASE-9393 的核心思想是通过 HDFS API 关闭 HBase 两个地方打开的 Socket;

RS 打开 HFile 读取元数据信息(flush、bulkload、move、balance 时)后关闭 Socket;每次执行完成用户 scan 操作后关闭 Socket。

优化效果:CLOSE_WAIT 数量降为 10 左右

4.2 DN 慢盘导致 RS 阻塞优化

问题描述:由于集群某个磁盘出现坏道(没有完全坏,表现为读写慢,disk.io.util 为 100%),导致 RS 所有 handler 线程因为写 WAL 失败而被阻塞,无法对外提 供服务,严重影响了用户读写数据体验。
最后分析发现,RS 写 WAL 时由于 DN 节点出现磁盘坏道(表现为 disk.io.util 为长时间处于 100%),导致写 WAL 的 pipeline 抛出异常并误将正常 DN 节点标记为 bad 节点,而恢复 pipeline 时使用 bad 节点进行数据块 transfer,导致 pipeline 恢复失败,最终 RS 的所有写请求都阻塞到 WAL 的 sync 线程上,RS 由于没有可用的 handler 线程,也就无法对外提供服务了。

解决办法:RS 配置 RPC 读写分离:避免由于写阻塞所有 handler 线程,影响到读请求;

pipeline 恢复失败解决:社区已有该问题的讨论,见并 HDFS-9178,不过因为 HDFS 的 pipeline 过程非常复杂,HDFS-9178 能否解决该问题需要进一步验证。

4.3 Compact 占用 Region 读锁优化

问题描述:某次有一个业务执行 BulkLoad 操作批量导入上 T 的数据到 HBase 表时,RS 端报 BulkLoad 操作获取 Region 级写锁出现超时异常:failed to get a lock in 60000 ms,当时该表并没有进行读写操作,最终定位到是该时间段内这个业务 的表正在进行 compact 操作,在我们的 HBase 版本中,执行 compact 时会获取 Region 级的读锁,而且会长时间占用,所有导致 BulkLoad 获取写锁超时了。

解决办法:Compact 时不持有 Region 读锁,社区对该问题的讨论见 HBASE-14575。

4.4 HTablePool 问题优化

问题描述:我们的 SCF 服务最初是基于 HTablePool API 开发的,SCF 服务在运 行一段时间后经常会出现 JVM 堆内存暴增而触发 FGC 的情况,分析发现 HTablePool 已经是标记为已废弃,原因是通过 HTablePool 的获取 Table 对象,会创建单独的线程池,而且线程个数没有限制,导致请求量大时,线程数会暴增。

解决办法:最后我们换成了官方推荐的 API,通过 Connection 获取 Table,这种方式 Connection 内部的线程池可以在在所有表中共享,而且线程数是可配置的。

4.5 其他优化

BlockCache 启用 BuckCache;Compact 限流优化等。

5. 总结
Apache HBase 实战技术总结 – 中国 HBase 技术社区
本文从多租户支持、数据读写接口、数据导入导出和平台优化四个方面讲解了 HBase 相关的平台建设工作。HBase 作为一个开源的平台,有着非常丰富的生态 系统。在 HBase 平台基础之上,我们持续不断地引入了各种新的能力,包括 OLAP、 图数据库、时序数据库和 SQL on HBase 等,这些我们将在 58HBase 平台实践和应用的后续篇章中进一步介绍。


转载
文章作者:何良均/张祥——58 同城 资深研发工程师

相关实践学习
云数据库HBase版使用教程
  相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情: https://cn.aliyun.com/product/hbase   ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4月前
|
存储 搜索推荐 关系型数据库
用户画像系列——HBase 在画像标签过期策略中的应用
用户画像系列——HBase 在画像标签过期策略中的应用
55 0
|
1月前
|
SQL 关系型数据库 MySQL
Sqoop【付诸实践 01】Sqoop1最新版 MySQL与HDFS\Hive\HBase 核心导入导出案例分享+多个WRAN及Exception问题处理(一篇即可学会在日常工作中使用Sqoop)
【2月更文挑战第9天】Sqoop【付诸实践 01】Sqoop1最新版 MySQL与HDFS\Hive\HBase 核心导入导出案例分享+多个WRAN及Exception问题处理(一篇即可学会在日常工作中使用Sqoop)
89 7
|
4月前
|
消息中间件 Java 关系型数据库
【Spring Boot+Kafka+Mysql+HBase】实现分布式优惠券后台应用系统(附源码)
【Spring Boot+Kafka+Mysql+HBase】实现分布式优惠券后台应用系统(附源码)
90 2
|
6月前
|
存储 NoSQL 分布式数据库
HBase在订单系统的应用
HBase在订单系统的应用
|
分布式数据库 数据库 Hbase
|
分布式数据库 Apache Hbase
《HBase应用与发展之Apache HBase的现状和发展》电子版地址
HBase应用与发展之Apache HBase的现状和发展
85 0
《HBase应用与发展之Apache HBase的现状和发展》电子版地址
|
分布式数据库 Hbase
|
搜索推荐 分布式数据库 Hbase
|
分布式数据库 Hbase