如何让 HBase 更快、更稳、更省钱

汤友棚 2019.07.29

概述

Apache HBase 是 Apache Hadoop 生态体系中的大规模、可扩展、分布式的数据存储服务。同时它还是 NoSQL 数据库。它的设计初衷是为包含了数百万列的数十亿行记录提供随机的、强一致性的实时查询。

默认情况下,HBase 的数据会保存在 HDFS 上,HBase 为 HDFS 做了很多优化来保证稳定性与性能。但是维护 HDFS 本身一点也不轻松,要不断进行监控、运维、调优、扩容、灾难恢复等一系列事情,而且在公有云上搭建 HDFS 的费用也是相当高的(文末有对比)。

为了节省费用、降低维护成本,一些用户使用 S3(或其他对象存储)存储 HBase 的数据。使用 S3 省去了监控运维的麻烦,同时还实现了存储计算分离,让 HBase 的扩容缩容都变得更加容易。但是 S3 不是文件系统,很多 HDFS 的 API 在 S3 上并没有对应的实现,同时 S3 的部分 API 没有强一致性保证,所以 HBase 的稳定性和性能都受到了影响。

下面我们来对比一下用 JuiceFS 做 HBase 数据存储的情况。

JuiceFS 简介

JuiceFS 是 HDFS 在公有云上的一种自然进化,首先它提供的高性能、分布式元数据服务完全兼容 HDFS API。同时又利用 S3 等对象存储弹性、低成本、服务化的优势,用它来做数据存储。

让我们来看看 JuiceFS 架构图:

JuiceFS 由两个主要部分组成:

  1. JuiceFS 元数据(Metadata)服务。
  2. JuiceFS Java SDK 完全兼容 HDFS API,同时也提供基于 FUSE 的客户端挂载,完全兼容 POSIX。

有兴趣深入了解可以查看官方文档

更快

工程师都关注性能,首先就来跑个 Benchmark。

我们使用 YCSB 测试集,希望模拟线上生产环境中 HBase 集群恢复的场景,所以测试是在已经跑过一遍然后重启 HBase 的情况下进行的。

测试环境:

  • 使用 AWS EMR
  • Core 节点 2 个,4 核 16G,500G EBS SSD
  • Region server 内存 6G

写入对比

S3 和 HDFS 写入性能基本一致。而 JuiceFS 则有大约 70% 的提升。 由于 HBase 使用的是 LSM 树,它会使用日志文件和一个内存存储结构把随机写操作转换为顺序写,因此主要考验的就是文件系统的顺序写能力,JuiceFS 采用并发多线程写入,加上高性能的元数据能力,所以比直接使用 S3 快很多。

单条 GET 对比

可以看到,使用 S3 时启动非常缓慢,主要是因为没有本地磁盘缓存,需要依靠 HBase Bucket Cache 来在磁盘上缓存数据,用来提高缓存命中率,而这部分数据在 RegionSever 重启后会丢失,所有的数据都必须去 S3 读取,需要大量时间重新预热,在上图中表现很明显。 当数据预热完成后,性能逐渐接近,此时热数据已经缓存在 HBase 的 Block Cache。

JuiceFS 支持数据缓存,可以把热数据完全缓存在本地磁盘上面。因此在 HBase 重启时,热数据依然可以通过本地磁盘中的缓存快速启动。

如果使用 SSD 做本地缓存盘,可以天然实现冷热数据分离的效果,冷数据在使用很少的情况下会自动从缓存中被淘汰,热数据会一直留在本地缓存盘上。

从测试中看,JuiceFS 和 HDFS 性能相当。也就是说 JuiceFS 在存储计算分离的情况下达到了 HDFS data locality 的性能水平。

更稳

使用 S3 做存储时,由于性能问题,WAL 并不能直接写在 S3 上,因此用户仍然需要额外维护一个 HDFS 集群来存放 WAL 数据。所以并没有彻底省去 HDFS 的搭建、监控、运维等工作量。

同时,因为 S3 不是文件系统,这为 HBase 稳定运行带来了很大的难度。举两个例子:

第一,S3 API 有一部分是最终一致性保证。所以在 HBase 中写入数据触发 flush 时,可能会出现 FileNotFoundException,或者出现新写入的数据不能立即可见的情况,这些都会导致 HBase 运行不稳定。

再来一个例子,S3 没有原子的 rename 操作,而 HBase 在 drop 表的时候需要做,因此只能通过其他方式去实现,一方面稳定性受到影响,另一方面 drop 表的时候还要消耗大量时间。

JuiceFS 解决了上面的问题。首先 WAL 可以直接写在 JuiceFS 上,就不用再维护 HDFS 了。同时 JuiceFS 保证数据强一致性,同时完全兼容 HDFS API,所以上面提到的两个问题都不会出现,运行稳定性和性能与 HDFS 不分仲伯。

更省钱

接下来主要讲讲为什么公有云上维护 HDFS 成本高。

首先,HDFS 在公有云上要使用云盘搭建,因为云盘已经做了多副本,加上 HDFS 要求的多副本,会让数据过渡冗余,增加很多成本。但是如果 HDFS 不做多副本,DataNode 会有单点故障的可用性问题。

第二,HDFS 是与计算资源耦合在一起的,如果存储空间不够了,HDFS 扩容也要一起增加很多 CPU 和内存,而集群的计算负载很可能并不高,完全用不上这些新增的资源,造成浪费。如果是存储计算分离架构,存储可以弹性扩容,就不会有这种情况发生了。

第三,说说弹性。HDFS 需要手动扩容,每次需要扩容都是增加一定量的空间,数据会逐渐存进来。如果扩的容量少,就要经常扩,工作量很大。如果扩的多,资源利用率就低,造成成本上升。而 S3 和 JuiceFS 这类弹性存储服务就不用考虑扩容,数据可以随意写入,存多少付多少钱,没有浪费。

下面让我们详细算算账。

各存储每月每 GB 价格:

  1. Amazon EBS 通用型 SSD (gp2) 卷:0.132 USD
  2. Amazon EBS 吞吐量优化型 HDD (st1):0.0594 USD
  3. S3 标准存储:0.024 USD
  4. JuiceFS:0.02 USD

按照 100T 数据量计算:

  1. SSD 和 HDD 做 HDFS 数据盘,需要有 3 倍系数,同时需要考虑 1.3 倍冗余系数
  2. S3 和 JuiceFS 均需要 30% 的 SSD 盘做本地缓存

计算方法:

  • HDFS 价格计算方法为:每 GB 单价 x 容量 x 副本系数 x 冗余系数
  • S3 价格计算方法为:每 GB 单价 x 容量 + 硬盘缓存每 GB 单价 x 容量 x 缓存系数
  • JuiceFS 价格计算方法为:(S3 每 GB 单价 + JuiceFS 每 GB 单价)x 容量 + 硬盘缓存每 GB 单价 x 容量 x 缓存系数。

每月价格对比:

所以,还在用 HDFS 的兄弟们有没有觉得账单太贵,要优化呢?在用 S3 的要不要彻底解决稳定性问题呢?

详细部署方法请参考 通过 Hadoop FileSystem 的方式使用 JuiceFS