数仓hive锁(Hive Lock)

1 篇文章 0 订阅
1 篇文章 0 订阅

昨天数据仓库hive中一张中间表lock,导致所有依赖这个表的任务失败。影响挺大,借此总结一下以备后面查用。

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 concatenateX 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 concatenateX 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)锁表
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)解除锁
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 来关闭锁,优先保证插入数据成功,虽然此时读数据会有问题。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
针对电商数仓Hive优化,可以从以下几个方面入手: 1. 数据分区:对于大规模数据的查询,使用分区表可以大幅度提高查询效率。可以按照日期、地域等维度进行分区。 2. 压缩存储:在Hive中,使用压缩存储可以减小数据的存储空间,同时也能提高查询效率。可以使用Gzip、Bzip2、Snappy等压缩方式。 3. 数据倾斜处理:在实际场景中,可能会出现某些字段的值非常集中,导致查询时某些节点负载过重,出现数据倾斜。可以采用一些技术手段,如随机数、哈希函数等进行数据均衡。 4. 动态分区:动态分区可以在查询的同时动态创建分区,避免手动创建分区的麻烦。 5. 合理设置参数:Hive的性能与参数设置密切相关,如MapReduce任务并行度、内存大小、IO缓存等。合理设置这些参数可以提高查询效率。 具体的优化参数包括: - hive.exec.dynamic.partition.mode:设置动态分区模式,可以设置为nonstrict或strict。 - hive.exec.dynamic.partition:是否允许动态分区,默认为true。 - hive.exec.max.dynamic.partitions:设置动态分区最大值。 - hive.exec.max.dynamic.partitions.pernode:每个节点的最大动态分区数。 - hive.auto.convert.join:是否开启自动转换Join,可以提高Join的效率。 - hive.optimize.bucketmapjoin.sortedmerge:是否开启Bucket Map Join Sorted Merge。 - hive.exec.parallel:设置MapReduce任务并行度。 - hive.vectorized.execution.enabled:是否开启矢量化查询。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值