写点什么

HBase 优化案例分析:Facebook Messages 系统问题与解决方案

2014 年 3 月 03 日

HDFS 设计的初衷是为了存储大文件(例如日志文件),面向批处理、顺序 I/O 的。然而架设在 HDFS 之上的 HBase 设计的初衷却是为了解决海量数据的随机读写的请求。把这两种设计初衷截然相反的组件怎么揉在一起的呢?这种分层的结构设计主要是为了使架构更清晰,HBase 层和 HDFS 层各司其职;但是却带来了潜在的性能下降。在很多业务场景中大家使用 HBase 抱怨最多的两个问题就是:Java GC 相关的问题和随机读写性能的问题。Facebook Messages(以下简称 FM 系统)系统可以说是 HBase 在 online storage 场景下的第一个案例(《 Apache Hadoop Goes Realtime at Facebook 》, SIGMOD 2011),最近他们在存储领域顶级会议 FAST2014 上发表了一篇论文《 Analysis of HDFS Under HBase: A Facebook Messages Case Study 》分析了他们在使用 HBase 中遇到的一些问题和解决方案,使用 HBase 做 online storage 的同学们可以参考下。

该论文首先讲了 Facebook 的分析方法包括 tracing/analysis/simulation,FM 系统的架构和文件与数据构成等,接下来开始分析 FM 系统在性能方面的一些问题,并提出了解决方案。

FM 系统的主要读写 I/O 负载

Figure 2 描述了每一层的 I/O 构成,解释了在 FM 系统对外请求中读占主导,但是由于 logging/compaction/replication/caching 导致写被严重放大。

  1. HBase 的设计是分层结构的,依次是 DB 逻辑层、FS 逻辑层、底层系统逻辑层。DB 逻辑层提供的对外使用的接口主要操作是 put() 和 get() 请求,这两个操作的数据都要写到 HDFS 上,其中读写比 99/1(Figure 2 中第一条)。
  2. 由于 DB 逻辑层内部为了保证数据的持久性会做 logging,为了读取的高效率会做 compaction,而且这两个操作都是写占主导的,所以把这两个操作(overheads)加上之后读写比为 79/21(Figure 2 中第二条)。
  3. 相当于调用 put() 操作向 HBase 写入的数据都是写入了两份:一份写入内存 Memstore 然后 flush 到 HFile/HDFS,另一份通过 logging 直接写 HLog/HDFS。Memstore 中积累一定量的数据才会写 HFile,这使得压缩比会比较高,而写 HLog 要求实时 append record 导致压缩比( HBASE-8155 )相对较低,导致写被放大 4 倍以上。 Compaction 操作就是读取小的 HFile 到内存 merge-sorting 成大的 HFile 然后输出,加速 HBase 读操作。Compaction 操作导致写被放大 17 倍以上,说明每部分数据平均被重复读写了 17 次,所以对于内容不变的大附件是不适合存储在 HBase 中的。由于读操作在 FM 业务中占主要比例,所以加速读操作对业务非常有帮助,所以 compaction 策略会比较激进。

HBase 的数据 reliable 是靠 HDFS 层保证的,即 HDFS 的三备份策略。那么也就是上述对 HDFS 的写操作都会被转化成三倍的 local file I/O 和两倍的网络 I/O。这样使得在本地磁盘 I/O 中衡量读写比变成了 55/45。
4. 然而由于对本地磁盘的读操作请求的数据会被本地 OS 的 cache 缓存,那么真正的读操作是由于 cache miss 引起的读操作的 I/O 量,这样使得读写比变成了 36/64,写被进一步放大。 另外 Figure 3 从 I/O 数据传输中真正业务需求的数据大小来看各个层次、各个操作引起的 I/O 变化。除了上面说的,还发现了整个系统最终存储在磁盘上有大量的 cold data(占 2/3),所以需要支持 hot/cold 数据分开存储。

总的来说,HBase stack 的 logging/compaction/replication/caching 会放大写 I/O,导致业务逻辑上读为主导的 HBase 系统在地层实际磁盘 I/O 中写占据了主导。

FM 系统的主要文件类型和大小

FM 系统的几种文件类型如 Table 2 所示,这个是纯业务的逻辑描述。在 HBase 的每个 RegionServer 上的每个 column family 对应一个或者多个 HFile 文件。FM 系统中有 8 个 column family,由于每个 column family 存储的数据的类型和大小不一样,使得每个 column family 的读写比是不一样的。而且很少数据是读写都会请求的,所以 cache all writes 可能作用不大(Figure 4)。

对于每个 column family 的文件,90% 是小于 15M 的。但是少量的特别大的文件会拉高 column family 的平均文件大小。例如 MessageMeta 这个 column family 的平均文件大小是 293M。从这些文件的生命周期来看,大部分 FM 的数据存储在 large,long-lived files,然而大部分文件却是 small, short-lived。这对 HDFS 的 NameNode 提出了很大的挑战,因为 HDFS 设计的初衷是为了存储少量、大文件准备的,所有的文件的元数据是存储在 NameNode 的内存中的,还有有 NameNode federation。

FM 系统的主要 I/O 访问类型

下面从 temporal locality, spatial locality, sequentiality 的角度来看。

73.7% 的数据只被读取了一次,但是 1.1% 的数据被读取了至少 64 次。也就是说只有少部分的数据被重复读取了。但是从触发 I/O 的角度,只有 19% 的读操作读取的是只被读取一次的数据,而大部分 I/O 是读取那些热数据。

在 HDFS 这一层,FM 读取数据没有表现出 sequentiality,也就是说明 high-bandwidth, high-latency 的机械磁盘不是服务读请求的理想存储介质。而且对数据的读取也没有表现出 spatial locality,也就是说 I/O 预读取也没啥作用。

解决方案

1. Flash/SSD 作为 cache 使用。

下面就考虑怎么架构能够加速这个系统了。目前 Facebook 的 HBase 系统每个 Node 挂 15 块 100MB/s 带宽、10ms 寻址时间的磁盘。Figure 9 表明:a) 增加磁盘块数有点用;b) 增加磁盘带宽没啥大用;c) 降低寻址时间非常有用。

由于少部分同样的数据会被经常读取,所以一个大的 cache 能够把 80% 左右的读取操作拦截而不用触发磁盘 I/O,而且只有这少部分的 hot data 需要被 cache。那么拿什么样的存储介质做 cache 呢?Figure 11 说明如果拿足够大的 Flash 做二级缓存,cache 命中率会明显提高,同时 cache 命中率跟内存大小关系并不大。

注:关于拿 Flash/SSD 做 cache,可以参考 HBase BucketBlockCache( HBASE-7404 )

我们知道大家比较关心 Flash/SSD 寿命的问题,在内存和 Flash 中 shuffling 数据能够使得最热的数据被交换到内存中,从而提升读性能,但是会降低 Flash 的寿命, 但是随着技术的发展这个问题带来的影响可能越来越小。

说完加速读的 cache,接着讨论了 Flash 作为写 buffer 是否会带来性能上的提升。由于 HDFS 写操作只要数据被 DataNode 成功接收到内存中就保证了持久性(因为三台 DataNode 同时存储,所以认为从 DataNode 的内存 flush 到磁盘的操作不会三个 DataNode 都失败),所以拿 Flash 做写 buffer 不会提高性能。虽然加写 buffer 会使后台的 compaction 操作降低他与前台服务的 I/O 争用,但是会增加很大复杂度,所以还是不用了。最后他们给出了结论就是拿 Flash 做写 buffer 没用。

然后他们还计算了,在这个存储栈中加入 Flash 做二级缓存不但能提升性能达 3 倍之多,而且只需要增加 5% 的成本,比加内存性价比高很多(怎么感觉有点像 SSD 的广告贴)。

2. 分层架构的缺点和改进方案

如 Figure 16 所示,一般分布式数据库系统分为三个层次:db layer/replication layer/local layer。这种分层架构的最大优点是简洁清晰,每层各司其职。例如 db layer 只需要处理 DB 相关的逻辑,底层的存储认为是 available 和 reliable 的。

HBase 是图中 a) 的架构,数据的冗余 replication 由 HDFS 来负责。但是这个带来一个问题就是例如 compaction 操作会读取多个三备份的小文件到内存 merge-sorting 成一个三备份的大文件,这个操作只能在其中的一个 RS/DN 上完成,那么从其他 RS/DN 上的数据读写都会带来网络传输 I/O。

图中 b) 的架构就是把 replication 层放到了 DB 层的上面,Facebook 举的例子是 Salus,不过我对这个东西不太熟悉。我认为 Cassandra 就是这个架构的。这个架构的缺点就是 DB 层需要处理底层文件系统的问题,还要保证和其他节点的 DB 层协调一致,太复杂了。

图中 c) 的架构是在 a 的基础上的一种改进,Spark 使用的就是这个架构。HBase 的 compaction 操作就可以简化成 join 和 sort 这样两个 RDD 变换。

Figure 17 展示了 local compaction 的原理,原来的网络 I/O 的一半转化成了本地磁盘读 I/O,而且可以利用读 cache 加速。我们都知道在数据密集型计算系统中网络交换机的 I/O 瓶颈非常大,例如 MapReduce Job 中 Data Shuffle 操作就是最耗时的操作,需要强大的网络 I/O 带宽。加州大学圣迭戈分校(UCSD) 微软亚洲研究院(MSRA) 都曾经设计专门的数据中心网络拓扑来优化网络I/O 负载,相关研究成果在计算机网络顶级会议SIGCOMM 上发表了多篇论文,但是由于其对网络路由器的改动伤筋动骨,最后都没有成功推广开来。

Figure 19 展示了 combined logging 的原理。现在 HBase 的多个 RS 会向同一个 DataNode 发送写 log 请求,而目前 DataNode 端会把来自这三个 RS 的 log 分别写到不同的文件 / 块中,会导致该 DataNode 磁盘 seek 操作较多(不再是磁盘顺序 I/O,而是随机 I/O)。Combined logging 就是把来自不同 RS 的 log 写到同一个文件中,这样就把 DataNode 的随机 I/O 转化成了顺序 I/O。

作者简介

梁堰波,北京航空航天大学计算机硕士,美团网资深工程师,曾在法国电信、百度和 VMware 工作和实习过,这几年一直在折腾 Hadoop/HBase/Impala 和数据挖掘相关的东西,新浪微博 @DataScientist 。

2014 年 3 月 03 日 23:149321

评论

发布
暂无评论
发现更多内容

您的客户管理决策是否低于10毫秒?

VoltDB

5G 物联网 解决方案 电信

4面字节跳动,终于“跳进去”了! 分享一波字节的面经。

Java成神之路

Java 程序员 架构 面试 编程语言

论如何快速吃透算法?186道高阶算法题+学习资料程序员面试必备

比伯

Java 编程 架构 面试 程序人生

校招开始,你做好【终身成长】的准备了吗?

闲鱼技术

区块链电子证照应用赋能政府服务

13530558032

惊讶!阿里大佬总结的图解Java小册火了,完整版笔记开放下载

周老师

Java 编程 程序员 架构 面试

干货来袭!这份阿里内部面试题库已经助我拿到了5个大厂Offer!

Java王路飞

Java 程序员 架构 面试 阿里

五个问题,三大策略,手把手教你定制App性能监控方案

友盟全域数据

监控 应用性能 监控工具 告警设置 质量监控

Kubectl Plugin 推荐(三)| 插件开发篇

郭旭东

Kubernetes kubectl kubectl plugin

Java的“泛型”特性,你以为自己会了?(万字长文)

比伯

Java 编程 程序员 架构 计算机

对htmlMeta的实例详解

佰草

html5

Java程序员面试15家公司收到15份offer,月薪35K全靠这Java面试小抄(2021版)开源分享

云流

Java 程序员 面试

PC五年,华为如水

脑极体

吉他扒谱该怎么做?分享一款超好用的扒谱工具!

奈奈的杂社

云原生时代下,容器安全的“四个挑战”和“两个关键”

阿里巴巴云原生

容器 云原生 k8s 安全 监控

网易云音乐:基于分布式图学习PGL的推荐系统优化之路

百度开发者中心

阿里二面:什么是mmap?

艾小仙

Kubernetes入门——深入浅出讲Docker

百度开发者中心

Docker Kubernetes 云原生

uni-app跨端开发H5、小程序、IOS、Android(一):太强了,一次性搞定全端开发

黑马腾云

微信小程序 uni-app uniapp web前端 3月日更

微服务的下一步,离不开服务网格

xcbeyond

微服务 Service Mesh 服务网格 3月日更

最新阿里Java岗位四面面经分享:并发+JVM+事务+集群+秒杀架构+数据库等

Java成神之路

Java 程序员 架构 面试 编程语言

Kubernetes入门——Kubernetes工作原理及使用

百度开发者中心

#Kubernetes# #技术课程#

快手、饿了么、小红书等14家互联网企业面经分享,感谢60多位面试官让我更加认清我自己

Java成神之路

Java 程序员 架构 面试 编程语言

NAC公链——Nirvana NA公链白皮书

区块链第一资讯

挖矿 区块链+

Kyuubi: 网易数帆开源的企业级数据湖探索平台(架构篇)

网易数帆

大数据 spark 开源 Kyuubi

思维转换 - 更好的认识世界

石云升

程序员成长 思维模型 28天写作 3月日更

阿里P9春招特此分享:Java核心开发成长手册(2021版)涵盖所有p5-p8技术栈

比伯

Java 编程 架构 面试 程序人生

面试官:啥?SynchronousQueue是钟点房?

四猿外

Java 并发编程 高并发 并发 SynchronousQueue

案例+源码!阿里新产高并发技术小册太香了!内容涵盖高并发、网络编程、微服务、数据处理等诸多技术栈

程序员小毕

Java 程序员 面试 高并发 阿里

在vscode中go编码发生的问题整理

happlyfox

golang 学习 vscode 28天写作 3月日更

再迎巅峰!阿里内部Java编程思想全栈技术实录Github上线7天已经星标89K!

程序员小毕

Java 编程 程序员 架构 面试

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

HBase优化案例分析:Facebook Messages系统问题与解决方案-InfoQ