Kafka工作原理与过程

1 消息路由策略

        在通过API方式发布消息时,生产者是以Record为消息进行发布的。Record中包含key与value,value才是我们真正的消息本身,而key用于路由消息所要存放的Partition。消息要写入到哪个Partition并不是随机的,而是有路由策略的。
1) 若指定了partition,则直接写入到指定的partition;
2) 若未指定partition但指定了key,则通过对key的hash值与partition数量取模,该取模结果就是要选出的partition索引;
3) 若partition和key都未指定,则使用轮询算法选出一个partition;

4) 若即指定了partition同时也指定了key,那么优先按照partition写入,如果指定的partition无效,则通过key取模写入。

public class OneProducer {
    // 第一个泛型:当前生产者所生产消息的key
    // 第二个泛型:当前生产者所生产的消息本身
    private KafkaProducer<Integer, String> producer;

    public OneProducer() {
        Properties properties = new Properties();
        // 指定kafka集群
        properties.put("bootstrap.servers", "kafkaOS1:9092,kafkaOS2:9092,kafkaOS3:9092");
        // 指定key与value的序列化器
        properties.put("key.serializer", "org.apache.kafka.common.serialization.IntegerSerializer");
        properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

        this.producer = new KafkaProducer<Integer, String>(properties);
    }

    public void sendMsg() {
        // 创建消息记录(包含主题、消息本身)  (String topic, V value)
        // ProducerRecord<Integer, String> record = new ProducerRecord<>("cities", "tianjin");
        // 创建消息记录(包含主题、key、消息本身)  (String topic, K key, V value)
        // ProducerRecord<Integer, String> record = new ProducerRecord<>("cities", 1, "tianjin");
        // 创建消息记录(包含主题、partition、key、消息本身)  (String topic, Integer partition, K key, V value)
        ProducerRecord<Integer, String> record = new ProducerRecord<>("cities", 0, 1, "tianjin");
        producer.send(record);
    }
}

2 消息写入算法(流程)

        消息生产者将消息发送给broker,并形成最终的可供消费者消费的log,是一个比较复杂的过程。

1) producer向broker集群提交连接请求,其所连接上的任意broker都会向其发送broker controller的通信URL,即配置文件中的listeners地址
2) 当producer指定了要生产的topic后,其会向broker controller发送请求,请求当前topic中所有partition的leader列表地址
3) broker controller在接收到请求后,会从zk中查找到指定topic的所有partition的leader,并返回给producer
4) producer在接收到leader列表地址后,根据消息路由策略找到当前要发送消息所要发送的partition leader,然后将消息发送给该leader
5) leader将消息写入本地log,并通知ISR中的followers
6) ISR中的followers从leader中同步消息后向leader发送ACK(正常情况要发送ACK应答)
7) leader收到所有ISR中的followers的ACK后,增加HW,表示消费者已经可以消费到该位置了

3 HW截断机制

        如果partition leader接收到了新的消息, ISR中其它Follower正在同步过程中,还未同步完毕时leader宕机;此时就需要选举出新的leader,若没有HW截断机制,将会导致partition中leader与follower数据的不一致。

Kafka无HW截断机制


        当原Leader宕机后又恢复时,将其LEO回退到其宕机时的HW,然后再与新的Leader进行数据同步,这种机制称为HW截断机制。HW截断机制可能会引发消息的丢失

Kafka-HW截断机制

 

4 消息发送的可靠性机制 

        生产者向kafka发送消息时,可以选择需要的可靠性级别。通过acks参数的值进行设置。

(1) 0值
        异步发送。生产者向kafka发送消息而不需要kafka反馈成功ack。该方式效率最高,但可靠性最低,其可能会存在消息丢失的情况。

  • 在传输过程中丢失:由于网络原因,生产者发送的消息根本就没有到达Kafka,但生产者不知道,其会一直生产并发送消息给Kafka,这种情况可能会出现大量的消息丢失。
  • 在broker中丢失:当broker的缓存满时正准备给partation中写入时,此时到达的新的消息会丢失。

(2) 1值
        同步发送,默认值。生产者发送消息给kafka,broker的partition leader在收到消息后马上发送成功ack,生产者收到后知道消息发送成功,然后会再发送消息。如果一直未收到kafka的ack,则生产者会认为消息发送失败,会重发消息。

        该方式不能保证消息发送成功,该方式仍会出现消息丢失的情况。例如,当leader收到 消息后马上向producer发送的ack,但此时在follower还没有同步数据时,该leader挂了。此时写入到原来leader中的消息就丢失了。因为这条消息对于producer来说,是发送成功了。但对于剩余的follower来说根本就没有存在过。

(3) -1值
        同步发送。生产者发送消息给kafka,kafka收到消息后要等到ISR列表中的所有副本都同步消息完成后,才向生产者发送成功ack。如果一直未收到kafka的ack,则认为消息发送失败,会自动重发消息。
        该方式很少会出现消息丢失的情况,但其存在消息重复接收的情况;为了解决重复接收(注意,重复接收,不是重复消费,这是两个概念)问题,Kafka允许为消息指定唯一标识,并允许用户自定义去重机制。

5 消费者消费过程解析

生产者将消息发送到topic中,消费者即可对其进行消费,其消费过程如下:
1) consumer向broker集群提交连接请求,其所连接上的任意broker都会向其发送broker controller的通信URL,即配置文件中的listeners地址
2) 当consumer指定了要消费的topic后,其会向broker controller发送消费请求
3) broker controller会为consumer分配一个或几个partition leader,并将该partitioin的当前offset发送给consumer
4) consumer会按照broker controller分配的partition对其中的消息进行消费
5) 当消费者消费完该条消息后,消费者会向broker发送一个该消息已被消费的反馈,即该消息的offset
6) 当broker接到消费者的offset后,会更新到相应的__consumer_offset中
7) 以上过程一直重复,直到消费者停止请求消息
8) 消费者可以重置offset,从而可以灵活消费存储在broker上的消息

6 Partition Leader选举范围

        当leader宕机后broker controller会从ISR中选一个follower成为新的leader。但,若ISR中没有其它的副本怎么办?可以通过unclean.leader.election.enable的取值来设置Leader选举的范围。
(1) false
        必须等待ISR列表中有副本活过来才进行新的选举。该策略可靠性有保证,但可用性低。

(2) true
        在ISR中没有副本的情况下可以选择任何一个没有宕机主机中该topic的partition副本作为新的leader,该策略可用性高,但可靠性没有保证。

7 重复消费问题及解决方案

最常见的重复消费有两种:
(1) 同一个consumer重复消费
        当Consumer由于消费能力较低而引发了消费超时时,则可能会形成重复消费。在时间到达时恰好某数据消费完毕,正准备提交offset但还没有提交时,时间到了。此时就会产生重复消费问题。
        其解决方案是,延长offset提交时间。
(2) 不同的consumer重复消费
        当Consumer消费了消息但还未提交offset时宕机,则这些已被消费过的消息会被重复消费。
        其解决方案是将自动提交改为手动提交。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值