hbase 学习(十四) Facebook针对hbase的优化方案分析

使用hbase的目的是为了海量数据的随机读写,但是在实际使用中却发现针对随机读的优化和gc是一个很大的问题,而且hbase的数据是存储在Hdfs,而Hdfs是面向流失数据访问进行设计的,就难免带来效率的下降。下面介绍一下Facebook
Message系统在HBase online storage场景下的一个案例(《Apache
Hadoop Goes Realtime at Facebook
》, SIGMOD
2011),最近他们在存储领域顶级会议FAST2014上发表了一篇论文《Analysis
of HDFS Under HBase: A Facebook Messages Case
Study
》分析了他们在使用HBase中遇到的一些问题和解决方案。该论文首先讲了Facebook的分析方法包括tracing/analysis/simulation,FM系统的架构和文件与数据构成等,接下来开始分析FM系统在性能方面的一些问题,并提出了解决方案。

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

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

  • HBase的设计是分层结构的,依次是DB逻辑层、FS逻辑层、底层系统逻辑层。DB逻辑层提供的对外使用的接口主要操作是put()和get()请求,这两个操作的数据都要写到HDFS上,其中读写比99/1(Figure
    2中第一条)。

  • 由于DB逻辑层内部为了保证数据的持久性会做logging,为了读取的高效率会做compaction,而且这两个操作都是写占主导的,所以把这两个操作(overheads)加上之后读写比为79/21(Figure
    2中第二条)。

  • 相当于调用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。

  • 然而由于对本地磁盘的读操作请求的数据会被本地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%的成本,比加内存性价比高很多。

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。

时间: 2024-08-28 02:30:54

hbase 学习(十四) Facebook针对hbase的优化方案分析的相关文章

Oracle学习(十四):管理用户安全

--用户(user) SQL> --创建名叫 grace 密码是password 的用户,新用户没有任何权限 SQL> create user grace identified by password; 验证用户: 密码验证方式(用户名/密码) 外部验证方式(主机认证,即通过登陆的用户名) 全局验证方式(其他方式:生物认证方式.token方式) 优先级顺序:外部验证>密码验证 --权限(privilege) 用户权限有两种: System:允许用户执行对于数据库的特定行为,例如:创建表.

android学习十四(android的接收短信)

收发短信是每个手机基本的操作,android手机当然也可以接收短信了.android系统提供了一系列的API,使得我们可以在自己的应用程序里接收和发送短信. 其实接收短信主要是利用我们前面学过的广播机制.当手机接收到一条短信的时候,系统会发出一条值为andorid.provider.Telephony.SMS_RECEIVED的广播,这条广播里携带着与短信相关的所有数据.每个应用程序都可以在广播接收器里对它进行监听,收到广播时在从中解析出短信的内容即可. 下面我们来个具体的例子实践下吧,新建一个

CSS基础学习十四:盒子模型补充之display属性设置

我在CSS基础学习十三:盒子模型的i博文只是阐释了CSS盒子模型,并没有过多的使用实例来演示.这篇博文 就来做一些盒子模型知识的补充.这一部分对于网页总体布局还是蛮重要的,过去大多数使用HTML中的table元素和 框架标签来进行网页的整体布局,现在我们使用最多的是DIV+CSS网页布局.所以一定要掌握好盒子模型,记住 content,border,padding和margin各自在盒子中的作用和使用方式. 先来看一个完整元素的盒子模型实例: <!DOCTYPE html PUBLIC "

Python学习十四:filter()

Python 中内置了filter()函数用于过滤序列. 用法: filter()接收一个函数和一个序列.filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素. demo: 1.在一个list中,删掉偶数,只保留奇数: #filter odd number in the list def is_odd(n): return n % 2 == 1 print filter(is_odd , [1 , 2 , 3 , 4 , 5 , 6 , 9

Java学习十四

学习内容: 1.Junit 一.Junit实例演示步骤 1.引入jar包 junit包需要引入hamcrest-core包,否则会报错 2.测试如下代码 1 package com.junit.test; 2 3 public class Calculator { 4 private static int result; //静态变量,用于存储运行结果 5 public void add(int n){ 6 result=result+n; 7 } 8 public void substract

Java编程思想学习(十四) 枚举

关键字enum可以将一组具名的值有限集合创建一种为新的类型,而这些具名的值可以作为常规的程序组件使用. 基本enum特性 调用enum的values()方法可以遍历enum实例,values()方法返回enum实例数组,且数组中元素保持在enum声明时的顺序. 1 public class TestEnum { 2 public static void main(String[] args) { 3 Fruit[] values = Fruit.values(); 4 for (Fruit fr

JS学习十四天----server端运行JS代码

server端运行JS代码 话说,当今不在client使用JS代码才是稀罕事.因为web应用的体验越来越丰富,client用JS实现的逻辑也越来越多,这造成的结果就是某些差点儿一致的逻辑须要在client和服务端各实现一遍,大牛们当然不甘心啊!幸运的是,我们能够在server端运行JS代码,谁让JS抱了一根大腿呢... 比如,现在在client使用JS进行验证已经是个标准,他能够有效避免用户在正常情况下提交错误的数据,增强用户体验.当然,server端的验证也是不可缺少的,由于这才是安全性的体现

nginx学习十四 ngx_master_process_cycle(master进程)

ngx_master_process_cycle()函数,这个函数会启动工作进程干活,并且会处理信号量,处理的过程中会杀死或者创建新的进程,具体流程如下: http://blog.csdn.net/xiaoliangsky/article/details/40866855 a)  阻塞所有nginx关心的信号: b)  设置进程的title(如果你用ps –aux来查看就可以分清master与worker进程,这就是title的作用.): c)  按照ngx_core_conf_t中worker

android 学习十四 探索安全性和权限

1.部署安全性:应用程序必须使用数字证书才能安装到设备上. 2.执行期间的安全性: 2.1 使用独立进程 2.2 使用固定唯一用户ID 2.3  申明性权限模型 3数字证书 3.1.数字证书的用处:使用数字证书对应用进行签名后,防止应用程序被非法更新(只有相同的数字证书才能更新应用) 3.2.数字证书:包含相关信息(如:公司名称和地址等)的工件. 重要特性包括(签名和公/私钥). 3.3.数字证书的获取:a.从证书授权机构购买 b.使用keytool等工具生成. 3.4数字证书的存储:存储在密钥