Apache HBase 中等对象存储(Medium Object Storage, 下面简称 MOB)的特性是由 HBASE-11339 引入的。该功能可以提高 HBase 对中等尺寸文件的低延迟读写访问(理想情况下,文件大小为 100K 到 10MB),这个功能使得 HBase 非常适合存储文档,图片和其他中等尺寸的对象。Apache HBase MOB 功能的实现是通过分离文件引用和 MOB 对象的 IO 路径来实现的,将不同的压缩策略应用于 MOB,从而降低了 HBase 压缩造成的写放大(write amplification)。MOB 对象存储在称为 MOB region 的特殊 region 中。表的 MOB 对象作为 MOB 文件存储在 MOB region 中,这意味着在该区域将存储大量的 MOB 文件。有关Apache HBase MOB 架构,请参见下图。
如果想及时了解Spark、Hadoop或者Hbase相关的文章,欢迎关注微信公共帐号:iteblog_hadoop
最初,MOB 文件相对较小(比 1到2个 HDFS 块小)。为了提高 Apache HDFS 的效率,MOB 文件通过称为 MOB compaction 的操作定期地合并到较大的文件中,这个压缩操作独立于正常的压缩过程。MOB 压缩的初始版本将一天中多个 MOB 文件合并为较大 MOB 文件。我们通过下面的例子进行说明。表 t1 有两个 regions(r1,r2),它有一个列族(f1)并且启用了 MOB。你可以看到有两个前缀: D279186428a75016b17e4df5ea43d080 对应于区域 r1 的开始键的 Hash 值, D41d8cd98f00b204e9800998ecf8427e 对应于区域 r2 的起始键的 Hash 值。对于区域 r1 来说,它在 20160101 和 20160102 里面各有两个 MOB 文件,对于区域 r2 来说,在 MOB 区域的 20160101 上有3个 MOB 文件,具体如下:
>ls /hbase/data/mobdir/data/default/t1/78e317a6e78a0fceb27b9fa0cb9dcf5b/f1
D279186428a75016b17e4df5ea43d08020160101f9d9713ab2fb4a8b825485f6a8acfcd5
D279186428a75016b17e4df5ea43d08020160101af7713ab2fbf4a8abc5135f6a8467ca8
D279186428a75016b17e4df5ea43d080201601029013ab2fceda8b825485f6a8acfcd515
D279186428a75016b17e4df5ea43d080201601029a7978013ab2fceda8b825485f6a8acf
D41d8cd98f00b204e9800998ecf8427e20160101fc94af623c2345f1b241887721e32a48
D41d8cd98f00b204e9800998ecf8427e20160101d0954af623c2345f1b241887721e3259
D41d8cd98f00b204e9800998ecf8427e20160101439adf4af623c2345f1b241887721e32
经过 MOB压缩之后,区域 r1 中 20160101 和 20160102 上的 MOB 文件各自合并成一个文件。区域 r2 的 20160101 上的三个 MOB 文件被压缩成一个文件。
D279186428a75016b17e4df5ea43d08020160101f49a9d9713ab2fb4a8b825485f6a8acf
D279186428a75016b17e4df5ea43d08020160102bc9176d09424e49a9d9065caf9713ab2
D41d8cd98f00b204e9800998ecf8427e20160101d9cb0954af623c2345f1b241887721e3
由于只有同一个区域、同一天的 MOB 文件可以压缩在一起,所以单个 MOB 区域目录下一年内一个特定 family 的 MOB 文件的最小界限将是 365 x区域数。1000 个区域在10年的时间经过 MOB 压缩后将生成 365×1000×10,365万个文件,并且还会不断地增长!不幸的是,Apache HDFS 对同一个目录下的文件数量有内存限制。如果 MOB 文件的数量超过 HDFS 的限制后,MOB 表将无法写入。 Apache HDFS 单个目录默认最大文件数量为100万。对于1,000个区域,它将在大约3年内达到此限制。区域越多,达到极限的速度越快。
为了解决这个问题,HBASE-16981引入了每周和每月的 MOB 压缩分区聚合策略,因数分别为7天或30天,以改善 MOB 文件计数扩展问题。
HBASE-16981 的基本思想是在一个日历周(calendar week)或一个日历月内将 MOB 文件压缩为更少,更大的文件。日历周是由 ISO 8601 定义的,从星期一开始,星期日结束。通常情况下,使用每周策略,MOB 压缩后每个区域每周将有一个文件; 使用每月策略,MOB 压缩之后每个区域每月将有一个文件。在一年内一个特定 family 的 MOB 区域目录下的 MOB 文件数量,在周策略的情况下将减少到 52 x 区域的数量(number- of- regions),在月策略的情况下将减少到 12 x 区域的数量。压缩后 大大减少了 MOB 文件的数量。
最初的方法
当 MOB 压缩发生时,HBase master 在一个日历月或一个日历周内将 MOB 文件聚合为更少,更大的文件。根据 MOB 压缩发生的频率,文件可能会被多次压缩。举个例子,假设我们使用每月聚合策略并对该月内的每天数据进行 MOB 压缩操作。在第一天,MOB 压缩将第一天的所有文件压缩为一个文件;第二天,MOB 压缩将第一天和第二天的文件压缩成新的文件;第三天,MOB 压缩将第二天的文件和第三天的文件压缩成一个新文件,这种操作将一直进行到这个月的最后一天。在这种情况下,第一天的文件被压缩了30次以上,因此写入 IO 的数量增加了30倍以上。
Apache HBase MOB 的设计目标是减少 MOB 压缩产生的写入放大,所以这种方式显然不合适。
最终实施的方法
为了解决这面方法的不足之处,HBASE-16981 引入了新的策略,下图展示了在每月压缩策略的情况下内部是什么工作的。
如果想及时了解Spark、Hadoop或者Hbase相关的文章,欢迎关注微信公共帐号:iteblog_hadoop
正如上图所示,MOB 压缩发生在20161115。基于 MOB 配置的阈值,当前日历周中的文件按照按照天进行压缩。也就是说,20161114这天的被压文件缩在一起;20161115这天的文件被压缩在一起。本月的日历周中文件是压缩在一起的。也就是说, 20161101 到 20161106 之间的文件被压缩在一起;20161107 到 20161113 之间 的文件被压缩在一起。过去几个月的文件基于月进行了压缩。也就是说,20161001 到 20161031 之间的文件被压缩在一起。大家可能注意到,2016年11月的第一个日历周是从 20161031 到 20161106,但是因为 20161031 属于过去的月,所以这天的数据被压缩到 201610 里面。所以导致 201611 月的第一个日历周只有6天的数据。如果 MOB 压缩阈值和 MOB 压缩批量大小配置的比较合适,经过压缩之后则会产生5个文件。
通过这种设计,MOB 文件在月策略的情况下最多只会压缩3次;在周策略的情况下最多只会压缩2次。更多细节请参见HBASE-16981。
MOB 的使用
默认情况下,MOB 压缩分区策略为天级别。要使用每周或每月的策略,我们需要使用 MOB 列族的MOB_COMPACT_PARTITION_POLICY 属性。用户可以在 HBase shell 创建表时设置此属性。
create 't1', {NAME => 'f1', IS_MOB => true, MOB_THRESHOLD => 1000000, MOB_COMPACT_PARTITION_POLICY => 'weekly’}
用户还可以通过 HBase shell 来更改已有表的 MOB_COMPACT_PARTITION_POLICY 属性。
alter 't1', {NAME => 'f1', MOB_COMPACT_PARTITION_POLICY => 'monthly'}
如果压缩策略从每天更改为每周或每月,或每周更改为每月,则下一个 MOB 压缩将重新压缩之前策略压缩过的 MOB 文件。如果策略从每月或每周更改为每天,或者每月更改为每周,则已经压缩过的 MOB 文件在新的压缩策略将不再被压缩。