hbase和hdfs的一些故事

本文深入探讨了HDFS在设计初期仅允许文件一次性写入且不可修改的特点,及其如何应对HBase引入的持久性需求。通过分析wal(Write-Ahead Log)机制的发展,解释了wal是如何在HDFS上存储操作日志,以及不同解决方案(如独立文件、共享文件和增加append操作)的优劣和最终选择。文章详细说明了sync功能的引入及其与append操作的关系,最后讨论了HDFS同步功能的发展历程及在不同Hadoop版本中的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hdfs一开始设计的时候,文件是只能写入一次,然后就只读的.一开始工作的相安无事,但是有一天,hbase跑到了hdfs上,hbase作为数据库,总要保持一定的持久性,所以它弄了个log,叫做wal,记录每一次操作,这样就算region server系统崩溃,Memstore的东西毁于一旦,还是可以靠wal来恢复.问题在于wal是存储在hdfs上的,hdfs上的文件只有被正确close以后,才是合法的hdfs文件.因此我认为wal有以下几种方案
1 每次操作产生的wal都成为单独的hdfs文件.这个方案产生的hdfs文件太多,不现实
2 只保持一个wal文件在hdfs上处于open,每次操作产生的wal都write到这个wal上,用类似fsync的功能把wal持久化到hdfs,定期close这个wal文件切换到下一个.这个方案问题在于hdfs当时没有fsync这样的功能,只有把这个wal close以后,这个wal才是合法的.假设系统一小时使用一个wal,在59分钟的时候系统崩溃,这个wal的前59分钟数据就等于丢失了.
3 hdfs增加append操作,每次hbase产生wal,都append到原来的wal文件上

2和3的区别是2是长时间保持一个文件打开,每次把wal写入,到一定时候再close这个文件.3则是需要每次append wal到一个已经close的文件上.

后来hdfs选择了方案3,增加了append操作.不幸的是,hdfs增加的append操作bug挺多,他们最终又打算把这个append去掉.但是有一些开发者在这期间搞出来了sync(我感觉是这期间搞出来的,但是很怀疑为什么把sync放到append的branch里,不明白sync为什么依赖append),sync可以保证hbase的持久性(我感觉是使方案2成为了可能),但是要想使用sync需要首先设置dfs.support.append.也就是说想要sync就不得不启用有缺陷的append.
而且当时append和sync这两个重要功能是在hadoop的branch "0.20.append",这个branch基于branch "0.20.2",而基于"0.20.2"这个branch的还有一个"0.20.security"的branch,包含了security的功能.所以导致一个开发者说,"there has been an 18 month period where there has been no one Apache release that had all the committed features of Apache Hadoop"(无力吐槽了,按理说branch应该merge回trunk的).下面的图表显示了当时的状态.
难怪另一个开发者说"HDFS sync has a colorful history"


[img]http://dl2.iteye.com/upload/attachment/0105/7313/f3ffb286-4d0c-337f-a333-ef9b7c8f3f9a.png[/img]


[img]http://dl2.iteye.com/upload/attachment/0105/7315/ab54e69f-3cb5-3df0-b3b7-975ed12fcd95.png[/img]

后面的故事总算回归正轨(其实是中间过程我懒得看了):
[url]https://issues.apache.org/jira/browse/HDFS-3120[/url]

hadoop 1.x: sync始终启用,"dfs.support.appends"配置项去掉,隐藏了append功能
hadoop 2.x: hsync/hflush始终启用,"dfs.support.appends"配置项可以用来开启append功能,该配置项默认启用.

[quote]The work on branch-20-append was to support sync, for durable HBase WALs, not append. The branch-20-append implementation is known to be buggy. There's been confusion about this, we often answer queries on the list like this. Unfortunately, the way to enable correct sync on branch-1 for HBase is to set dfs.support.append to true in your config, which has the side effect of enabling append (which we don't want to do).
For v1.x let's:
Always enable the sync path (currently only enabled if dfs.support.append is set)
Remove the dfs.support.append configuration option. Let's keep the code paths though in case we ever fix append on branch-1, in which case we can add the config option back
For 2.x let's
Always enable the hsync/hflush path
The dfs.support.appends only enables the append specific paths (since the hsync/hflush paths are now always on). Append will still default to being enabled so there is no net effect by default.[/quote]

其实hdfs的hsync/hflush也有一番曲折(HDFS sync has a colorful history),但那是另一个故事了.

所以我们这些上来就用hadoop 2.x的人,是多么幸运啊
参考资料如下

[url]http://blog.cloudera.com/blog/2012/01/an-update-on-apache-hadoop-1-0/[/url]
[url]http://blog.cloudera.com/blog/2009/07/file-appends-in-hdfs/[/url]
[url]http://hadoop-hbase.blogspot.com/2012/05/hbase-hdfs-and-durable-sync.html[/url]
### HBaseHDFS的区别及关系 #### 1. 数据存储模型 HBase 是一种分布式列族数据库,基于 Google 的 BigTable 设计[^4]。它提供了随机读写访问能力以及大规模数据处理的支持。而 HDFS(Hadoop Distributed File System)是一个分布式的文件系统,主要用于批量数据的高效存储管理。HDFS 提供的是高吞吐量的数据访问模式,适合一次写入多次读取的工作负载。 HBase 使用 HDFS 来持久化其底层数据,这意味着所有的 HBase 表数据最终都会被存储到 HDFS 中[^3]。具体来说,HBase 将其 MemStore 的更新记录保存在一个称为 Write-Ahead Log (WAL) 文件中,并定期将这些更改刷新到磁盘上的 HFile 中[^2]。 #### 2. 性能特点 由于设计目标不同,两者的性能特征也有所差异。HBase 更注重低延迟查询支持,能够满足实时应用的需求;相比之下,HDFS 则更擅长于大块数据流式操作,在批处理场景下表现优异。因此,当需要快速检索特定记录或者执行频繁的小规模 I/O 请求时,通常会选择使用 HBase 而不是直接通过 HDFS 进行交互[^1]。 #### 3. 故障恢复机制 对于未及时刷写的内存缓冲区中的变更内容(HBase内部称之为Memstore),如果发生节点崩溃等情况,则依靠之前提到过的预写日志(WAL)来进行灾难后的状态重建工作流程说明如下所示: ```python def hbase_recovery(): """ This function demonstrates the recovery process of HBase using WAL. It reads from the WAL files stored in HDFS to reconstruct lost data. """ wal_files = get_wal_files_from_hdfs() # Get all available WALs for file in wal_files: entries = parse_entries(file) for entry in entries: apply_entry_to_memstore(entry) ``` 上述伪代码展示了如何利用存储在 HDFS 上面的日志来完成系统的自我修复过程。 #### 4. 架构依赖性 两者都依赖于 Zookeeper 实现集群协调功能,比如选举 master 或者跟踪 region server 状态变化等重要任务。此外,它们还共同受益于其他组件如 YARN 执行资源调度等方面的优势。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值