spark并发写入hive表方案探讨

背景

hive表是不支持并发插入的,因为涉及到文件操作,并发写可能导致写过程中争夺一个文件失败,故想要实现并发写需要其他的方式来实现

方案一:采用hive事务,虽然控制了并发数,采用一个一个任务写,但是性能不高

方案二:采用分区,分区可以隔离文件操作,避免争夺文件导致失败,但是需要控制分区数量,分区太多会导致性能下降

方案三:替换其他数据库,如hbase

方案四:批量写入,将所有要写入的量汇总成一个批次写入,也就没有并发可言了。

技术选型

没有最好的方案,只有更合适的方案,结合目前团队业务,最好的还是采用分区写,但是需要控制分区数量。

实现方案

通过令牌桶实现,令牌数量是固定的,每次插入前来拿一个令牌,用完之后放回去,令牌桶用完了再来取的线程报错

业务目标

  1. 均匀插入到不同分区,使数据分散,这样能解决spark数据倾斜问题,提高查询效率

  2. 分区不能重复,会存在并发问题,同一时刻只能有一个线程往这个分区插入

因为要解决并发,首先就要考虑redis,然后就是redis数据类型的选型,这里采用redis zset,因为我们均匀插入不同分区,即要实现滚动向前的操作,所以利用score每次操作之后进行自增来实现滚动操作,zset的member存储所有值,score来解决占用和释放问题,和滚动向前的操作

member=1,score=1;

member=2,score=2;

.......

member=200,score=200;

操作步骤

  1. 线程1 获取分区号 从score[1~+inf]中获取一个,因为第一次获取,所以得到member=1,score=1;

  2. 线程1 获取到之后将score更新为member=1,score=0;

  3. 然后线程1 执行spark任务操作

  4. 此时线程2 也来获取分区号,同样从score[1~+inf]中获取一个,因为1被线程1 使用,这里获取到member=2,score=2;

  5. 线程2 获取到之后将score更新为member=2,score=0;

  6. 假设 线程2 处理较快,比线程1 先结束,线程2 开始释放分区号,member=2,score=max(score)+1即=201;

  7. 线程1执行结束开始释放分区号member=1,score=max(score)+1即=202;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值