美文网首页
Spark消费Kafka如何实现精准一次性消费?

Spark消费Kafka如何实现精准一次性消费?

作者: 鄙人王道长 | 来源:发表于2020-07-21 08:21 被阅读0次
    在这里插入图片描述

    1.定义

    • 精确一次消费(Exactly-once) 是指消息一定会被处理且只会被处理一次。不多不少就一次处理。

    如果达不到精确一次消费,可能会达到另外两种情况:

    • 至少一次消费(at least once),主要是保证数据不会丢失,但有可能存在数据重复问题。

    • 最多一次消费 (at most once),主要是保证数据不会重复,但有可能存在数据丢失问题。

    如果同时解决了数据丢失和数据重复的问题,那么就实现了精确一次消费的语义了。

    2. 问题如何产生

    数据何时会丢失: 比如实时计算任务进行计算,到数据结果存盘之前,进程崩溃,假设在进程崩溃前kafka调整了偏移量,那么kafka就会认为数据已经被处理过,即使进程重启,kafka也会从新的偏移量开始,所以之前没有保存的数据就被丢失掉了。

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

    3.解决方案

    方案一:利用关系型数据库的事务进行处理

    出现丢失或者重复的问题,核心就是偏移量的提交与数据的保存,不是原子性的。如果能做成要么数据保存和偏移量都成功,要么两个失败。那么就不会出现丢失或者重复了。

    这样的话可以把存数据和偏移量放到一个事务里。这样就做到前面的成功,如果后面做失败了,就回滚前面那么就达成了原子性。

    问题与限制

    1. 数据库选型受限, 只能使用支持事务的关系型数据库 ,如mysql, oracle ,无法使用其他功能强大的nosql数据库。

    2. 如果保存的数据量较大一个数据库节点不够,多个节点的话,还要考虑分布式事务的问题。做分布式事务,结构复杂,拖慢性能。

    3. 如果做本地事务 ,只能把分区数据提取到driver中进行保存,降低并发 ,增加executor到driver的数据传递io。

    方案二:手动提交偏移量+幂等性处理

    咱们知道如果能够同时解决数据丢失和数据重复问题,就等于做到了精确一次消费。

    那咱们就各个击破。

    首先解决数据丢失问题,办法就是要等数据保存成功后再提交偏移量,所以就必须手工来控制偏移量的提交时机。

    但是如果数据保存了,没等偏移量提交进程挂了,数据会被重复消费。怎么办?那就要把数据的保存做成幂等性保存。即同一批数据反复保存多次,数据不会翻倍,保存一次和保存一百次的效果是一样的。如果能做到这个,就达到了幂等性保存,就不用担心数据会重复了。

    难点

    话虽如此,在实际的开发中手动提交偏移量其实不难,难的是幂等性的保存,有的时候并不一定能保证。所以有的时候只能优先保证的数据不丢失。数据重复难以避免。即只保证了至少一次消费的语义

    文章已收录于https://github.com/wangsl123/dzblog,欢迎start。微信关注【鄙人王道长】,也可第一时间看到文章。

    相关文章

      网友评论

          本文标题:Spark消费Kafka如何实现精准一次性消费?

          本文链接:https://www.haomeiwen.com/subject/hnpbkktx.html