[翻译]HBase 中的 ACID
同前面翻译的一篇关联的,同作者的另一篇:ACID in HBase
这一篇不是单纯地描述一个问题,而是以 ACID 为主题,介绍了其在 HBase 中各个部分的体现及实现。
ACID,即:原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durability)。
HBase 支持特定场景下的 ACID,即对同一行的 Put 操作保证完全的 ACID(HBASE-3584增加了多操作事务,HBASE-5229增加了多行事务,但原理是一样的)
那么 HBase 内部的 ACID 是怎么样实现的呢?
HBase 实现了一种 MVCC,并且 HBase 没有混合读写事务。
由于历史的原因,HBase 的命名有点奇怪(下面会有提到)。
每个 RegionServer 拥有严格地单调递增的事务号。
一个写事务(一组 put 或 delete)开始时,该事务获取下一个最大的事务号,在 HBase 内叫做 WriteNumber。
一个读事务(一个 scan 或 get)开始时,该事务获取先前最新提交事务的事务号,在 HBase 内叫做 ReadPoint。
每个新创建的 KeyValue 对象用它所在事务的 WriteNumber 标记(由于历史的原因,这个标记在 HBase 内叫做 memstore timestamp,注意这个应用程序层面的、我们常说的时间戳是两回事)。
宏观地,HBase 写事务的流程是这样的:
- 对行(一行或多行)加锁,屏蔽对相同行的并发写;
- 获取当前的 WriteNumber;
- 提交修改到 WAL;
- 提交修改到 Memstore(用前面获取的 WriteNumber 标记修改的 KeyValues);
- 提交事务,也就是把 ReadPoint 更新为当前获取的 WriteNumber;
- 释放行(一行或多行)锁。
宏观地,HBase 读事务的流程是这样的:
- 打开 scanner;
- 获取当前的 ReadPoint;
- 用获取的 ReadPoint 过滤所有扫描到的 KeyValues(KeyValues 的 memstore timestamp > ReadPoint,只看 ReadPoint 之前的);
- 关闭 scanner(scanner 由客户端初始化)。
实际在实现的时候会比上面说的复杂,但是上述也足够说明问题。注意,reader 在读的过程中是完全不加锁的,但是我们依旧保证了 ACID。
需要注意的是:上述的机制只有在事务严格顺序提交的情况下管用。否则的话,一个先开始却未提交的事务将会对一个后开始先提交的事务可见(破坏了隔离性)。但是,HBase 中的事务一般都很短,所以这不是个问题。
HBase 确实实现了:所有事务顺序提交。
HBase 中提交一个事务,意味着将当前的的 ReadPoint 更新为该事务的 WriteNumber,这样就将事务提交的更改对所有新的 scan 可见。
HBase 维护一个未完成事务的列表,一个事务的提交会被推迟,直到先前的事务提交。注意:HBase 可以支持并发、所有的修改立即生效,只是提交的时候是顺序的。(译注:这里实际上隐含地表达了 HBase 性能优先,同时实现的是最终一致性)
由于 HBase 不保证任何 Region 之间(每个 Region 只保存在一个 Region Server 上)的一致性,故 MVCC 的数据结果只需保存在每个 RegionServer 各自的内存中。
下一个有趣的事儿,在 compaction 期间发生了什么?
HBase 的 Compaction 过程,通常将多个小的 store 文件(将 memstore flush 到磁盘时产生)合并成一个大点儿的,并在合并过程中移除垃圾。这里的"垃圾"要么是寿命超过了列族的 TTL(Time-To-Live)或 VERSIONS 设置、要么是被标记删除的那些 KeyValues。详情参见这里(Deletion in HBase, HBase data rentention options)。
假设在一个 scanner 扫描 KeyValues 过程中发生了 Compaction,scanner 可能会看到一个不完整的行(HBase 中对行的定义为:Introduction to HBase),即该行数据不可能从任何一种顺序事务调度得到。(译注:也就是发生了不一致)
HBase 的方案是跟踪所有打开的 scanner 使用的 ReadPoint 中最早的一个,然后滤掉所有大于该 ReadPoint 的 KeyValues。这一逻辑 连同其它的优化在HBASE-2856中增加进来,这一补丁后,允许 HBase 在并发 flush 的场景下保证 ACID。
HBASE-5569 为 delete marker 实现了同样的逻辑(译注:在 ReadPoint 过滤的逻辑,支持并发删除场景下的 ACID),HBase 是标记删除的,故实现了并发删除的 ACID。
最后,注意,当一个 KeyValue 的 memstore timestamp 比最老的scanner(实际是 scanner 持有的 ReadPoint)还要老时,会被清零(置为0),这样该 KeyValue会对所有的 scanner 可见,当然,此时比该 KeyValue 原 memstore timestamp 更早的 scanner 都已经结束了。
额外的几点:
- (对于写事务)即使事务失败了,ReadPoint 也会被更新,以避免阻拦后面等待提交的事务(从实现上说,其实是同一个过程,没什么特别的处理,更新 ReadPoint 的代码写在 Java 代码final{}语句块内)(译注:前面提到了HBase 的事务是顺序提交的,后面的事务会等待前面的事务提交);
- 更新写入到 WAL 后,所有的修改都只创建了一条记录(record),没有单独的 commit record(译注:我理解这个 commit record 可参考 2阶段提交);
- 当一台 RegionServer 挂掉,如果 WAL 已经完整写入,所有执行中的事务可以重放日志以恢复,如果 WAL 未写完,则未完成的事务会丢掉(相关的数据也丢失了)。
[翻译]HBase 中的 ACID的更多相关文章
- [翻译]HBase 的 MVCC 和内建的原子操作
翻译一篇:HBase MVCC and built-in Atomic Operations 作者:Lars Hofhansl HBase 有一些特殊的原子操作: checkAndPut, check ...
- HBase中的备份和故障恢复方法
本文将对Apache HBase可用的数据备份机制和大量数据的故障恢复/容灾机制做简要介绍. 随着HBase在重要的商业系统中应用的大量添加,很多企业须要通过对它们的HBase集群建立健壮的备份和故障 ...
- 浅谈Phoenix在HBase中的应用
一.前言 业务使用HBase已经有一段时间了,期间也反馈了很多问题,其中反馈最多的是HBase是否支持SQL查询和二级索引,由于HBase在这两块上目前暂不支持,导致业务在使用时无法更好的利用现有的经 ...
- 使用bulkload向hbase中批量写入数据
1.数据样式 写入之前,需要整理以下数据的格式,之后将数据保存到hdfs中,本例使用的样式如下(用tab分开): row1 N row2 M row3 B row4 V row5 N row6 M r ...
- [翻译]PYTHON中如何使用*ARGS和**KWARGS
[翻译]Python中如何使用*args和**kwargs 函数定义 函数调用 不知道有没有人翻译了,看到了,很短,顺手一翻 原文地址 入口 或者可以叫做,在Python中如何使用可变长参数列表 函数 ...
- java实现服务端守护进程来监听客户端通过上传json文件写数据到hbase中
1.项目介绍: 由于大数据部门涉及到其他部门将数据传到数据中心,大部分公司采用的方式是用json文件的方式传输,因此就需要编写服务端和客户端的小程序了.而我主要实现服务端的代码,也有相应的客户端的测试 ...
- 使用Hive或Impala执行SQL语句,对存储在HBase中的数据操作
CSSDesk body { background-color: #2574b0; } /*! zybuluo */ article,aside,details,figcaption,figure,f ...
- HBase中的压缩算法比较 GZIP、LZO、Zippy、Snappy [转]
网址: http://www.cnblogs.com/panfeng412/archive/2012/12/24/applications-scenario-summary-of-compressio ...
- sqoop将关系型的数据库得数据导入到hbase中
1.sqoop将关系数据库导入到hbase的参数说明
随机推荐
- 如何使用iOS 8 指纹识别,代码、示例
像想象,iOS 8指纹是非常容易使用的.只是需要能够获得一个接口,弹出屏幕模式框,随着app store在相同的. 直接上的条形码.以下代码是从复制Apple官方文件. 加入LocalAuthenti ...
- ABP之动态WebAPI
ABP之动态WebAPI ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 ...
- BestCoder-Round#33
写在前面 这是我第一次做BestCoder, 熟悉的外观BestCoder模式. BC上不仅能看到英文, 背部Chinese view是中文题目 交的次数是会影响得分的. 所以有了把握再交. 至少例子 ...
- tortoise svn无法识别subversion check向下代码来解决
使用eclipse小工具subversion check代码后,tortoise svnclient(版本号1.8.8)无法识别,不显示svn图标. 根据每个试验后的线上不实际的解决方案.试过的方法: ...
- 多重集组合数 (DP)
输入: n=3 m=3 a={1,2,3} M=10000 输出: 6 (0+0+3,0+1+2,0+2+1,1+0+2,1+1+1,1+2+0) 为了不重复计数,同一种类的物品最好一次性处理好.于 ...
- 承诺c指针 (1)指针是地址
(1)是地址 首先明白一个观点:指针就是地址.这是理解指针的起始一步. 直观感受下.变量的地址 int main() { int foo; int *foo_p; foo = 5; foo_p = & ...
- hdu 3449 (有依赖的01背包)
依赖背包 事实上,这是一种树形DP,其特点是每个父节点都需要对它的各个儿子的属性进行一次DP以求得自己的相关属性. fj打算去买一些东西,在那之前,他需要一些盒子去装他打算要买的不同的物品.每一个盒子 ...
- 6最好的之一 HTML5/CSS3 演示(PPT)框架
HTML 是全世界最流行的网页编程语言.而HTML5是这门语言的升级版本号.越来越多的开发人员和设计师開始使用HTML5.以下介绍几个 HTML5/CSS3 的演示工具和框架,你能够用它们来创建你的网 ...
- MacOS10.9平台配置Appium+Java环境
1) 安装JDK 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html ...
- SSH—Struts(三)—跑步者(Action)
如已经描述Struts其基本原理和控制器ActionServlet,根据一个请求通过流ActionServlet之后就要到达Action类中做详细的处理了.ActionServlet通过ActionM ...