HBase 事务性 (Transaction)

本文介绍了数据库事务的概念,包括ACID属性,并探讨了HBase在0.94版本中对事务的有限支持,主要集中在单一行的操作。文章指出,对于跨行或跨表的事务处理,HBase存在局限性,可能导致一致性问题。为解决这个问题,提到了两个项目——yahoo/omid和Indexed Transactional HBase,作为扩展HBase事务能力的解决方案。

What is Transaction

先摘录一段Wiki关于Transaction(事务)的释义:

A transaction comprises a unit of work performed within a database management system (or similar system) against a database, and treated in a coherent and reliable way independent of other transactions. Transactions in a database environment have two main purposes:
1. To provide reliable units of work that allow correct recovery from failures and keep a database consistent even in cases of system failure, when execution stops (completely or partially) and many operations upon a database remain uncompleted, with unclear status.

2. To provide isolation between programs accessing a database concurrently. If this isolation is not provided, the program's outcome are possibly erroneous.
A database transaction, by definition, must be atomic, consistent, isolated and durable. Database practitioners often refer to these properties of database transactions using the acronym ACID.
Transactions provide an "all-or-nothing" proposition, stating that each work-unit performed in a database must either complete in its entirety or have no effect whatsoever. Further, the system must isolate each transaction from other transactions, results must conform to existing constraints in the database, and transactions that complete successfully must get written to durable storage.

其中,all-or-nothing很明确的表达了事务的本质:“要么全成功,要么什么都没发生过”。可以把它看作一个原子操作。



HBase Transaction

(注:这里经过补充与修改,第一天就被转载本博文这里的描述不够准确)

HBase的支持的事务很有限,0.94版本的新特性中有两条:

[HBASE-3584] - Allow atomic put/delete in one call.

[HBASE-5229] - Provide basic building blocks for "multi-row" local transactions.

第一条,我引用NoSQLFan的解读:

“0.94版本具备更完整的事务支持: 之前Hbase提供行级的事务,不过每次事务只能执行一个写操作,比如连续地执行一系列Put,Delete操作,那么这些操作是单独一个个的事务,其整体并不是原子性执行的。而在0.94版本中,可以实现Put、Delete在同一个事务中一起原子性执行。”

具体怎么用呢?有下面这一段Sample:

//Add API for atomic row mutations to HBase (currently Put and Delete).
Client API would look like this:
Delete d = new Delete(ROW);
Put p = new Put(ROW);
//...
AtomicRowMutation arm = new AtomicRowMutation(ROW);
arm.add(p);
arm.add(d);
myHtable.atomicMutation(arm);

可以看到,这里的事务仅仅是针对某一行的一系列Put/Delete操作。不同行、不同表间一系列操作是无法放在一个事务中的。

第二条,我的个人理解,这次是多行一并的事务了!不过貌似是“同一Region中的多行”。因为文中一句“ Global (cross region) transactions are not discussed here.

因此对一张多Region表来说,还是无法保证每次修改都能封装为一个事务。


What We Need

结合我之前的博文《HBase多条件查询》,我们通常需要为了查询而建立多个索引表。

比如我Save一条player数据,主表(信息完整表)的rowKey是以ID构成,顺序排列。

我如果需要按player的积分(Scores)排个TOP 10,我可能还需要用(Max - player.getScores) + ID建一张索引表。同理可能还有多个……

每当插入一条player记录,我需要同时对这两个rowKey进行put操作。

这,就已经超出了HBase支持的事务范畴(同一行的一系列操作事务)。

此处无事务会怎样?比如我新增一个player,首先执行IDTbl.put,再执行ScoresTbl.put。

在执行第二步ScoresTbl.put时与HBase Cluster的网络中断了,此时ScoresTbl.put超时失败,但IDTbl.put已经成功完成了。

如果仅仅在业务层做了RollBack,此时应该会执行IDTbl.delete,但是网络中断,delete操作一样会失败。

网络恢复了!

最终,我们新增的这位Player登录进来(因为IDTbl.put中有他的记录,所以可以成功登录)。

在点击“查看我的排名”按钮时会触发ScoresTbl.get操作,但ScoresTbl中没有他的记录,对后续操作会有不可预知的影响。

如果,我们有10几张索引表……

因此,事务是必须的!


What Can We Do

为了解决这种不同记录、不同表间的事务问题,我看到两个项目。

1、yahoo/omid


The Omid project provides transactional support for key-value stores using Snapshot Isolation. Omid stands for Optimistically transactional Management in Datastores. At this stage of the project, HBase is the only supported data-store.

使用方式可以参考项目中的:

从Sample中看,我认为会与Spring Hadoop的hbaseTemplate有冲突,因为hbaseTemplate一次只能获得唯一的HTable实例……

2、Indexed Transactional HBase


描述更是简单:Transactional and indexing extensions for hbase

不过从github代码的更新记录来看,貌似已经2年没更新了,支持到0.90……


其他解决方案,我也会继续寻找,也请有过HBase事务应用的大牛们留言指个方向。谢谢 ^_^

Author:Pirate Leo
blog:http://blog.youkuaiyun.com/pirateleo
email:codeevoship@gmail.com
转载请注明出处,谢谢。
由于文中在发布后难免会有勘误或补充,推荐到本博客中阅读本文。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值