(33)保证数据的精准一次性消费

2.5.1 定义
精确一次消费(Exactly-once)
是指消息一定会被处理且只会被处理一次。不多不少就一次处理。
如果达不到精确一次消费,可能会达到另外两种情况:
至少一次消费(at least once)
主要是保证数据不会丢失,但有可能存在数据重复问题。
最多一次消费 (at most once)
主要是保证数据不会重复,但有可能存在数据丢失问题。
2.5.2 问题如何产生
数据何时会丢失
比如实时计算任务进行计算,到数据结果存盘之前,进程崩溃,假设在进程崩溃前 kafka
调整了偏移量,那么 kafka 就会认为数据已经被处理过,即使进程重启,kafka 也会从新的
偏移量开始,所以之前没有保存的数据就被丢失掉了。

 

数据何时会重复
如果数据计算结果已经存盘了,在 kafka 调整偏移量之前,进程崩溃,那么
kafka 会
认为数据没有被消费,进程重启,会重新从旧的偏移量开始,那么数据就会被 2
次消费,
又会被存盘,数据就被存了 2 遍,造成数据重复

 

如果同时解决了数据丢失和数据重复的问题,那么就实现了精确一次消费的语义了。
目前 Kafka 默认每 5 秒钟做一次自动提交偏移量,这样并不能保证精准一次消费
enable.auto.commit 的默认值是 true;就是默认采用自动提交的机制。
auto.commit.interval.ms 的默认值是 5000,单位是毫秒。
2.5.3 如何解决
(1) 策略一:利用关系型数据库的事务进行处理
出现丢失或者重复的问题,核心就是偏移量的提交与数据的保存,不是原子性的。如果
能做成要么数据保存和偏移量都成功,要么两个失败,那么就不会出现丢失或者重复了。
这样的话可以把存数据和修改偏移量放到一个事务里。这样就做到前面的成功,如果后
面做失败了,就回滚前面那么就达成了原子性,这种情况先存数据还是先修改偏移量没影响。

 

好处
事务方式能够保证精准一次性消费
问题与限制
数据必须都要放在某一个关系型数据库中,无法使用其他功能强大的 nosql 数据
事务本身性能不好
如果保存的数据量较大一个数据库节点不够,多个节点的话,还要考虑分布式事务
的问题。分布式事务会带来管理的复杂性,一般企业不选择使用,有的企业会把分
布式事务变成本地事务,例如把 Executor 上的数据通过 rdd.collect 算子提取到
Driver 端,由 Driver 端统一写入数据库,这样会将分布式事务变成本地事务的单
线程操作,降低了写入的吞吐量
使用场景
数据足够少(通常经过聚合后的数据量都比较小,明细数据一般数据量都比较大),并
且支持事务的数据库
(2) 策略二:手动提交偏移量+幂等性处理
我们知道如果能够同时解决数据丢失和数据重复问题,就等于做到了精确一次消费。那
就各个击破。
首先解决 数据丢失问题 ,办法 就是要等数据保存成功后再提交偏移量 ,所以就必须手工
来控制偏移量的提交时机。
但是如果数据保存了,没等偏移量提交进程挂了,数据会被 重复消费 。怎么办?那就要
把数据的保存做成幂等性保存。即同一批数据反复保存多次,数据不会翻倍,保存一次和保
存一百次的效果是一样的。如果能做到这个,就达到了幂等性保存,就不用担心数据会重复
了。

 

难点
话虽如此,在实际的开发中手动提交偏移量其实不难,难的是幂等性的保存,有的时候
并不一定能保证,这个需要看使用的数据库,如果数据库本身不支持幂等性操作,那只能优
先保证的数据不丢失,数据重复难以避免,即只保证了 至少一次消费的语义
一般有主键的数据库都支持幂等性操作 upsert。
使用场景
处理数据较多,或者数据保存在不支持事务的数据库上
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据开发工程师-宋权

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值