zoukankan      html  css  js  c++  java
  • Kafka经典三大问:数据有序丢失重复

    Kafka经典三大问:数据有序丢失重复

    在kafka中有三个经典的问题:

    • 如何保证数据有序性
    • 如何解决数据丢失问题
    • 如何处理数据重复消费

    这些不光是面试常客,更是日常使用过程中会遇到的几个问题,下面分别记录一下产生的原因以及如何解决。

    1. 消息有序

    kafka 的数据,在同一个partition下是默认有序的,但在多个partition中并不一定能够保证其顺序性。kafka因为其自身的性质,适合高吞吐的流式大数据,对数据有序性要求不严格的场景比较适用。

    1.1. 为什么只保证单partition有序?

    如果Kafka要保证多个partition有序,不仅broker保存的数据要保持顺序,消费时也要按序消费。假设partition1堵了,为了有序,那partition2以及后续的分区也不能被消费,这种情况下,Kafka 就退化成了单一队列,毫无并发性可言,极大降低系统性能。因此Kafka使用多partition的概念,并且只保证单partition有序。这样不同partiiton之间不会干扰对方。

    1.2. 解决方式

    kafka自身没有提供整个topic级别的消息顺序性,但我们可以在业务层面来处理。

    可以通过message key来保证你需要保持顺序性的数据发送到同一个partition,即send方法,可以指定三个参数(topic, partition, key), partition和key是可选的,如果指定了同一个partition的话,那么数据就是有序的。

    同时在消费端,只创建一个消费者来消费topic,但后续的话这个消费者可以写入N个内存队列,保证具有相同key的数据写入同一个内存队列即可。引入内存队列是为了解决业务处理单线程处理太慢的问题,多个内存队列可以起多个线程进行消费,同时具有相同key的数据在同一个内存队列中,这样就能保证顺序性。

    kafka_顺序性

    2. 数据丢失

    丢失数据一般分为两种情况:mq自己弄丢了,业务处理弄丢了。

    2.1. kafka弄丢了数据

    kafka的某个broker宕机,重新选举partition的leader时,如果其他的follower还没有完成数据同步,此时leader挂了,那么就有可能造成数据丢失的问题。

    kafka提供了几个参数来保证数据不丢失:

    • replication.factor:分区副本数,最低设置为2,即要求每个Partition至少拥有两个副本;

    • min.insync.replicas:要求一个leader感知到有至少一个follower还跟自己保持联系,没掉队,这样才能确保leader挂了还有一个follower;

    • acks:在producer发送数据成功后,kafka会给生产者返回一个ack信息,这个称为kafka的ack机制;

      ack有3个可选值,-1、0、1;

      • ack=1:producer只要收到一个分区副本写入成功的通知就认为推送消息成功,这个分区副本特指leader副本;

      • ack=0:producer发送一次就不再发送了,不管是否发送成功;

      • ack=-1:producer只有收到分区内所有副本的成功写入通知才算推送消息成功;

    • retries:重试次数,如果写入失败就会进行重试,直到超过retries设置的值;

    2.2. 消费端弄丢了数据

    例如消费者已经获取到这个数据,并且提交了offset,但后续在对数据进行业务操作的时候挂掉了,导致数据没有成功处理,这时候kafka认为你已经成功获取了,但实际没有,就造成了数据丢失的问题。

    一般情况下用手动提交的方式来解决,当数据处理成功后再提交offset。

    3. 重复消费

    ack=1的情况下,是有可能存在消息丢失的情况的,因为producer收到leader写入成功的通知就认为推送成功,但实际上leader副本在把消息同步到follower副本的时候失败了,这时候消息就丢失了。

    为了处理这种推送失败的情况,kakfa引入了回调机制来处理,实际上就是一种重试的方式,这时候会出现因为重试机制导致消息乱序的情况。

    3.1. 解决重试机制引起的消息乱序

    生产者Producer

    为了实现producer的幂等性,kafka引入了Producer IDSequence Number两个参数,对于每个生产者,该Producer发送的消息都对应一个单调增的Sequence Number。同样的Broker端也会为每个生产者的每条消息维护一个序号,并且每commit一条数据时就会将其序号递增。

    对于接收到的数据,如果其序号比Borker维护的序号大一(即表示是下一条数据),Broker会接收它,否则将其丢弃。

    如果消息序号比Broker维护的序号差值比一大,说明中间有数据尚未写入,即乱序,此时Broker拒绝该消息,Producer抛出InvalidSequenceNumber

    如果消息序号小于等于Broker维护的序号,说明该消息已被保存,即为重复消息,Broker直接丢弃该消息,Producer抛出DuplicateSequenceNumber

    Sender发送失败后会重试,这样可以保证每个消息都被发送到broker

    消费者Consumer

    同样的也是利用幂等性的原理来解决,可以给每条数据加上一个唯一标识,进行数据处理的时候校验这个标识是否存在,如果存在即为重复数据,丢弃。

  • 相关阅读:
    Appium问题解决方案(2)- AttributeError:module 'appium.webdriver' has no attribute 'Remote'
    Azure Messaging-ServiceBus Messaging消息队列技术系列8-服务总线配额
    Azure Messaging-ServiceBus Messaging消息队列技术系列7-消息事务
    Azure Messaging-ServiceBus Messaging消息队列技术系列6-消息回执
    Azure Messaging-ServiceBus Messaging消息队列技术系列5-重复消息:at-least-once at-most-once
    Azure Messaging-ServiceBus Messaging消息队列技术系列4-复杂对象消息是否需要支持序列化和消息持久化
    Azure Messaging-ServiceBus Messaging消息队列技术系列3-消息顺序保证
    [博客迁移]探索Windows Azure 监控和自动伸缩系列3
    [博客迁移]探索Windows Azure 监控和自动伸缩系列2
    [博客迁移]探索Windows Azure 监控和自动伸缩系列1
  • 原文地址:https://www.cnblogs.com/yisany/p/14736360.html
Copyright © 2011-2022 走看看