【编者按】近日发布的Hive 0.13中采用了ACID语义的事务机制,在分区层保证事务原子性、一致性和持久性,并通过开启ZooKeeper或内存中的锁机制保证事务隔离性。数据流摄取、缓慢变化维、数据重述这些新的用例在新版本中成为了可能,当然新版Hive中也还存在一些不足,Hive新版本具体带来哪些改变呢?作者Alan Gates为我们带来了精彩分析。
以下为原文:
什么是ACID,有什么作用?
ACID代表数据库事务中的4个特性,原子性(任何一个数据库操作要么被完整执行,要么完全不执行)、一致性(一旦应用程序执行了一个操作,操作的结果对于每一个之后的操作都是可见的)、隔离性(一个用户的操作不会对其他用户产生意料之外的副作用)、持久性(一旦一个操作被完成,这些操作也将被记录下来,即使机器或者系统出现故障,也要保证这些记录的完整性)。这些特性一直被认为是事务功能的重要组成部分。
在最近发布的Hive 0.13中,事务的原子性、一致性和持久性在分区层得到保证,隔离性则通过开启ZooKeeper或内存中可用的锁机制来保证。通过在Hive 0.13中加入事务,实现在行级提供全部的ACID语义,这样的话,一个应用程序可以添加行,而另一个应用程序可以从同一分区中读取数据,互相之间不会产生干扰。
采用ACID语义的事务机制被添加到Hive中来处理以下的用例:
不足:
流摄入接口
有关使用流数据摄入的详细信息,请参阅StreamingDataIngest。
语法变化
多个新命令被添加到Hive的DDL中以支持ACID和事务,一些现有的DDL也被做了一些修改。
例如:新加入的SHOW TRANSACTIONS命令,有关该命令的详细信息,请参阅ShowTransactions。
SHOW COMPACTIONS也是一个新加入的命令,详细信息请参阅ShowCompactions。
原有的SHOW LOCKS命令被修改,以提供与事务相关的新锁信息。如果你正在使用ZooKeeper或者内存锁命令,你会注意到这条命令在输出上并没有多大改变,详细信息请参阅ShowLocks。
ALTER TABLE中添加了一个新的选项,用来压缩表或分区。一般用户不需要去请求压缩,因为系统会检测到他们的需求,然后自动启动压缩。但是,如果一个表压缩被意外终止或者一个用户想要去手动压缩表,ALTER TABLE可以满足用户,提供手动启动压缩,有关详细信息,请参阅AlterTable/PartitionCompact。ALTER TABLE会将请求排入队列、压缩并返回请求,如果用户想看到压缩的进展情况,可以使用SHOW COMPACTIONS命令。
基础设计
HDFS不支持对文件进行更改。在写入者向文件进行写入操作,同时文件被其他用户读取这种情况下,它无法保证读取的一致性。为了在HDFS上提供这一功能,我们采用在其他数据仓库工具使用的标准方法,将表或分区数据存储在一组基础文件中,将新记录、更新和删除操作存储在delta文件中。 为每个事务创建一组新delta文件(或者在流代理如:Flume或Storm中,为每一批事务创建一组新delta文件),更改表或分区。在读取时,读取器将基础文件和delta文件合并,应用更新和删除操作。
有时这些变化需要合并成基础文件,一组线程必须添加到Hive metastore中。他们确定什么时候需要压缩,然后执行压缩,最后进行清理(删除旧文件)。压缩的类型分两种,次要的和主要的。次要压缩采用一组现有的delta文件,并为每一次bucket重写一个delta文件。主要压缩则要为每个bucket写一个或多个delta文件,为每一次bucket重写一个新基础文件。所有压缩都在后台完成,并不妨碍数据的并发读取和写入。在一次压缩后,系统会等待直到所有旧文件的读取结束,然后删除旧的文件。
以前一个分区(或如果没有分区表的表)的所有文件都放在单个目录中。因为这些变化,所有采用ACID思想写入的分区都将有一个基础文件的目录,以及delta文件集目录。
新锁管理器DbLockManager也添加到了Hive中。该锁管理器将所有锁信息存储在metastore中,此外所有事务也存储在metastore中。这意味着事务和锁即使在服务器出现故障时也能保证持久性,为了避免客户端死机、离开或者锁挂起,锁持有者和事务启动器需要向metastore发出心跳信号(heartbeat),如果在给定的时间内服务器没有收到客户端发出的心跳信号,该锁或事务将被中止。
配置
许多新配置关键项被添加到系统用以支持事务。
配置关键项 |
默认值 |
事务启动值 |
注释 |
hive.txn.manager |
org.apache.hadoop. hive.ql.lockmgr. DummyTxnManager |
org.apache.hadoop. hive.ql.lockmgr. DbTxnManager |
DummyTxnManager延用了Hive 0.13之前的做法,不提供事务。 |
hive.txn.timeout |
300 |
如果在这段时间内,客户端没有发出心跳信号,事务就会被宣告终止。 |
|
hive.txn.max. open.batch |
1000 |
事务的最大数量,可以用open_txns()获取。 |
|
hive.compactor. initiator.on |
false |
true (for exactly one instance of the Thrift metastore service) |
是否在该metastore实例上运行启动器和垃圾清理线程。 |
hive.compactor. worker.threads |
0 |
> 0 on at least one instance of the Thrift metastore service |
有多少工作线程在该metastore实例上运行。 |
hive.compactor. worker.timeout |
86400 |
压缩作业在该时间内未完成将被宣布失败,压缩操作被重新排入队列。 |
|
hive.compactor. check.interval |
300 |
检查是否有分区需要被压缩。 |
|
hive.compactor. delta.num.threshold |
10 |
delta目录的数目,达到该数后将触发次要压缩。 |
|
hive.compactor. delta.pct.threshold |
0.1 |
与基础文件中delta文件的百分比,达到该值会触发主要压缩。(1 = 100%) |
|
hive.compactor. abortedtxn.threshold |
1000 |
给定分区中已中止事务的数目,达到该数会也会触发主要压缩。 |
hive.txn.max.open.batch控制多个事务流代理,如Flume或Storm。流代理将多个词条写到单个文件中(每个Flume代理或每个Storm螺栓)。因此,增加该值可以减少流代理创建的文件数,但增加此值也增加了开放事务的数目(Hive需要追踪),这可能会影响读取的性能。
工作线程为压缩操作产生了许多MapReduce作业,而它们自身并没有做压缩。确定进行表压缩后,增加工作线程的数目会减少表压缩的时间。随着更多的MapReduce作业在后台运行,Hadoop集群的后台负载也在增加。
减小此值将减少压缩表或分区的时间。当然,首先得检查压缩是否必要,这需要为每个表或分区调用多个NameNode,降低此值可以减少NameNode的负载。
表属性
如果表的所有者不希望系统自动确定何时要压缩,那么可以手动设置表属性NO_AUTO_COMPACTION,用来阻止所有的自动压缩操作。
原文链接:ACID and Transactions in Hive (翻译/毛梦琪 责编/魏伟)以“ 云计算大数据 推动智慧中国 ”为主题的 第六届中国云计算大会 将于5月20-23日在北京国家会议中心隆重举办。产业观察、技术培训、主题论坛、行业研讨,内容丰富,干货十足。票价优惠,马上 报名 !