Hive Lock 理论与实践

标签: hive | 发表时间:2017-06-09 00:45 | 作者:
出处:https://my.oschina.net/leejun2005

0、背景

最近两天数据仓库中一张核心表遭遇了锁的问题,导致数据插入失败,影响挺大,之前一直没注意到这个问题,借此总结一下这块的知识和遇到的坑。

hive 在 0.7 版本之后开始支持并发,线上的环境默认是用 zookeeper 做 hive 的锁管理,Hive开启并发功能的时候自动开启锁功能。

1、Hive 锁的类型与关系

hive 目前主要有两种锁,SHARED(共享锁 S)和 Exclusive(排他锁 X)。共享锁 S 和  排他锁 X 它们之间的兼容性矩阵关系如下:

总结起来就是:

  • 1)查询操作使用共享锁,共享锁是可以多重、并发使用的
  • 2)修改表操作使用独占锁,它会阻止其他的查询、修改操作
  • 3)可以对分区使用锁。

以下情况会出发锁,以及它的类型和锁定范围如下:

Hive Command

Locks Acquired

select .. T1 partition P1

S on T1, T1.P1

insert into T2(partition P2) select .. T1 partition P1

S on T2, T1, T1.P1 and X on T2.P2

insert into T2(partition P.Q) select .. T1 partition P1

S on T2, T2.P, T1, T1.P1 and X on T2.P.Q

alter table T1 rename T2

X on T1

alter table T1 add cols

X on T1

alter table T1 replace cols

X on T1

alter table T1 change cols

X on T1

alter table T1  concatenate X on T1

alter table T1 add partition P1

S on T1, X on T1.P1

alter table T1 drop partition P1

S on T1, X on T1.P1

alter table T1 touch partition P1

S on T1, X on T1.P1

alter table T1 set serdeproperties

S on T1

alter table T1 set serializer

S on T1

alter table T1 set file format

S on T1

alter table T1 set tblproperties

X on T1

alter table T1 partition P1 concatenate X on T1.P1

drop table T1

X on T1

2、如何开启锁机制

修改hive-site.xml,配置如下:

  <property>
    <name>hive.zookeeper.quorum</name>
    <value>zk1,zk2,zk3</value>
  </property>
<property>
    <name>hive.support.concurrency</name>
    <value>true</value>
</property>

除此之外,还可以手动显式设置独占锁:

  -- 1)锁表
hive> lock table t1 exclusive;
-- 表被独占锁之后,将不能执行查询操作:
hive> SELECT COUNT(*) FROM people;
conflicting lock present for default@people mode SHARED
FAILED: Error in acquiring locks: locks on the underlying objects
cannot be acquired. retry after some time

-- 2)解除锁
hive> unlock table t1;

注:Lock 是一种悲观的顺序化机制。它假设很可能发生冲突,因此在操作数据时,就加锁。

如果冲突的可能性很小,多数的锁都是不必要的。比如 Innodb 实现了一个延迟加锁的机制,来减少加锁的数量,提升性能,在代码中称为隐式锁(Implicit Lock),Hive 中的默认是隐式锁。

3、如何 debug lock

可以使用以下命令开始debug和排查锁问题:

  SHOW LOCKS <TABLE_NAME>;
SHOW LOCKS <TABLE_NAME> EXTENDED;
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>);
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>) EXTENDED;

比如我们执行以下语句就可以知道是那个SQL锁Hive表了:

  show locks hdp_ubu_zhuanzhuan_defaultdb.token extended

4、如何关闭锁

hive的锁在某些情况下会影响job的效率。在对数据一致性要求不高,或者已经明确了解到lock不会对job产生影响的情况下可以在session级别关闭lock的支持,又或者在表被任务循环持续读取时,insert 插入失败(建议脚本重跑一段时间范围数据时设置 sleep 间隔,避免长期持有锁,造成依赖表的任务调度失败)。我们可以通过  set hive.support.concurrency=false 参数在 session 中关闭锁, 这个参数为 false 既能保证session忽略任何锁强行操作数据,又能保证session里的SQL对表不加任何锁

  • 场景1:离线下载分析商业cdn的qos job。

使用load data将数据导入hive中,hive的表按 dt,hour,domain进行明确分区,因此,是否有锁对数据的一致性影响不大,反而有了锁之后,job之间就会有锁竞争的问题(报错信息:conflicting lock present for table  mode EXCLUSIVE)。

调整 job:

  hive --database cdnlog -e "
    set hive.support.concurrency=false;
    load data local inpath 'file' 
    OVERWRITE into table chinanetcenter_log_origin 
    partition(dt='2013-12-17',hour='04',domain='xxx')
"

数据load时就不会有报错了,效率也高了不少

  • 场景2:hive锁的几个配置,可以在锁冲突时 fail fast 或者 重试等待锁释放
  hive.lock.numretries #重试次数
hive.lock.sleep.between.retries #重试时sleep的时间

hive默认的sleep时间是60s,比较长,在高并发场景下,可以减少这个的数值来提供job的效率。

Hive(CDH4.2.0)的锁处理流程:

  1.首先对query进行编译,生成QueryPlan

2.构建读写锁对象(主要两个成员变量:LockObject,Lockmode)
  对于非分区表,直接根据需要构建S或者X锁对象
  对于分区表:(此处是区分input/output)
If S mode:
    直接对Table/related partition 构建S对象
Else:
    If 添加新分区:
        构建S对象
    Else
        构建X对象
End

3.对锁对象进行字符表排序(避免死锁),对于同一个LockObject,先获取Execlusive

4.遍历锁对象列表,进行锁申请
While trynumber< hive.lock.numretries(default100):
    创建parent(node)目录,mode= CreateMode.PERSISTENT
    创建锁目录,mode=CreateMode.EPHEMERAL_SEQUENTIAL
    For Child:Children
        If Child已经有写锁:
            获取child写锁seqno
        If mode=X 并且 Child 已经有读锁
            获取child读锁seqno
        If childseqno>0并且小于当前seqno
            释放锁
        Trynumber++
    Sleep(hive.lock.sleep.between.retries:default1min)

总结:

想要避免 Hive 锁造成的读、写失败问题,注意以下3点:

1、表建议设置分区,锁的粒度可以到分区,否则容易遭遇长时间锁表,尤其大字典表、单张全量表要注意。
2、建议脚本重跑一段时间范围数据时设置 sleep 间隔,避免长期持有锁,造成依赖表的任务调度失败。
3、我们可以通过 set hive.support.concurrency=false 来关闭锁,优先保证插入数据成功,虽然此时读数据会有问题。

Refer:

[1] Hive Concurrency Model:Locking

https://cwiki.apache.org/confluence/display/Hive/Locking

[2] Hive Locks -- Table/Partition Level

https://community.mapr.com/docs/DOC-1299

[3] hive lock的配置问题

http://caiguangguang.blog.51cto.com/1652935/1344453

[4] MySQL数据库InnoDB存储引擎中的锁机制 

http://www.uml.org.cn/sjjm/201205302.asp

[5] mysql锁机制浅析(1)

https://segmentfault.com/a/1190000004507047

相关 [hive lock 理论] 推荐:

Hive Lock 理论与实践

- - leejun2005的个人页面
最近两天数据仓库中一张核心表遭遇了锁的问题,导致数据插入失败,影响挺大,之前一直没注意到这个问题,借此总结一下这块的知识和遇到的坑. hive 在 0.7 版本之后开始支持并发,线上的环境默认是用 zookeeper 做 hive 的锁管理,Hive开启并发功能的时候自动开启锁功能. hive 目前主要有两种锁,SHARED(共享锁 S)和 Exclusive(排他锁 X).

[Oracle] enq: TX - row lock contention 优化案例

- - CSDN博客推荐文章
根据开发反馈,最近每天早上7:30应用会报警,应用的日志显示数据库连接池满了,新的连接被拒绝. 首先,我做了ASH报告(报告区间:7:25 ~ 7:35),从ASH的等待事件发现enq: TX - row lock contention居然高达76.54%,如下所示:. enq: TX - row lock contention等待事件是一种行的等待事件,也就是说同一时刻有多个session请求修改同一行.

Redis实现lock互斥访问资源

- - 数据库 - ITeye博客
Redis是当前很流行的一种开源键值数据库. 目前睿思的后台架构在数据库层采用了Redis和MySQL组合的形式,其中Redis主要用来存储状态信息(比如当前种子的peer)和读写频繁的数据. Redis完全运行在内存之上,无lock设计,速度非常快. 通过实测,在睿思服务器上读写速度达到3万次/s.

hive调优

- - 互联网 - ITeye博客
一、    控制hive任务中的map数: . 1.    通常情况下,作业会通过input的目录产生一个或者多个map任务. 主要的决定因素有: input的文件总个数,input的文件大小,集群设置的文件块大小(目前为128M, 可在hive中通过set dfs.block.size;命令查看到,该参数不能自定义修改);.

hive 优化 tips

- - CSDN博客推荐文章
一、     Hive join优化. 也可以显示声明进行map join:特别适用于小表join大表的时候,SELECT /*+ MAPJOIN(b) */ a.key, a.value FROM a join b on a.key = b.key. 2.     注意带表分区的join, 如:.

Hive中的join

- - CSDN博客云计算推荐文章
select a.* from a join b on a.id = b.id select a.* from a join b on (a.id = b.id and a.department = b.department). 在使用join写查询的时候有一个原则:应该将条目少的表或者子查询放在join操作符的左边.

hive优化(2)

- - 开源软件 - ITeye博客
Hive是将符合SQL语法的字符串解析生成可以在Hadoop上执行的MapReduce的工具. 使用Hive尽量按照分布式计算的一些特点来设计sql,和传统关系型数据库有区别,. 所以需要去掉原有关系型数据库下开发的一些固有思维. 1:尽量尽早地过滤数据,减少每个阶段的数据量,对于分区表要加分区,同时只选择需要使用到的字段.

hive优化

- - 开源软件 - ITeye博客
hive.optimize.cp=true:列裁剪. hive.optimize.prunner:分区裁剪. hive.limit.optimize.enable=true:优化LIMIT n语句. hive.limit.optimize.limit.file=10:最大文件数.   1.job的输入数据大小必须小于参数:hive.exec.mode.local.auto.inputbytes.max(默认128MB).

Hive优化

- - 互联网 - ITeye博客
     使用Hive有一段时间了,目前发现需要进行优化的较多出现在出现join、distinct的情况下,而且一般都是reduce过程较慢.      Reduce过程比较慢的现象又可以分为两类:. 情形一:map已经达到100%,而reduce阶段一直是99%,属于数据倾斜. 情形二:使用了count(distinct)或者group by的操作,现象是reduce有进度但是进度缓慢,31%-32%-34%...一个附带的提示是使用reduce个数很可能是1.

hive bucket 桶

- - CSDN博客推荐文章
对于每一个表(table)或者分区,Hive可以进一步组织成桶. Hive也是针对某一列进行桶的组织. Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中. 采用桶能够带来一些好处,比如JOIN操作. 对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作. 那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量.