22-kafka消息中间件的介绍

十三、Kafka

13.1 异步通信原理

13.1.1 观察者(发布-订阅)模式

  1. 理解
    • 观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe)
    • 定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新
    • 一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知

13.1.2 生产者消费者模式

  1. 传统模式

    • 生产者直接将消息传递给指定的消费者
    • 缺点
      • 耦合性特别高,当生产者或者消费者发生变化,都需要重写业务逻辑
  2. 生产者消费者模式

    • 通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯

    image-20220708151222430

  3. 数据传递流程

    • 生产者消费者模式,即N个线程进行生产,同时N个线程进行消费,两种角色通过内存缓冲区进行通信
    • 生产者负责向缓冲区里面添加数据单元
    • 消费者负责从缓冲区里面取出数据单元
      • 一般遵循先进先出的原则

13.1.3 缓冲区

  1. 解耦
    • 假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖
  2. 支持并发
    • 生产者直接调用消费者的某个方法过程中函数调用是同步的
    • 万一消费者处理数据很慢,生产者就会白白糟蹋大好时光
  3. 支持忙闲不均
    • 缓冲区还有另一个好处。如果制造数据的速度时快时慢,缓冲区的好处就体现出来了。
    • 当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。
    • 等生产者的制造速度慢下来,消费者再慢慢处理掉。

13.1.4 数据单元

  1. 关联到业务对象
    • 数据单元必须关联到某种业务对象
  2. 完整性
    • 就是在传输过程中,要保证该数据单元的完整
  3. 独立性
    • 就是各个数据单元之间没有互相依赖
    • 某个数据单元传输失败不应该影响已经完成传输的单元;也不应该影响尚未传输的单元。
  4. 颗粒度
    • 数据单元需要关联到某种业务对象。那么数据单元和业务对象应该处于的关系(一对一?一对多)
    • 如果颗粒度过小会增加数据传输的次数
    • 如果颗粒度过大会增加单个数据传输的时间,影响后期消费

13.2 消息系统原理

一个消息系统负责将数据从一个应用传递到另外一个应用,应用只需要关注于数据,无需关注数据在两个或者多个应用间是如何传递的

13.2.1 点对点消息传递

  1. 理解点对点

    • 在点对点消息系统中,消息持久化到一个队列中。
  2. 特点

    • 此时,将有一个或多个消费者消费队列中的数据。但是一条消息只能被消费一次

    • 当一个消费者消费了队列中的某条数据之后,该条数据则从消息队列中删除

    • 点对点模式即使有多个消费者同时消费数据,也能保证数据处理的顺序

  3. 基于推送模型的消息系统,由消息代理记录消费状态

    • 消息代理将消息推送(push)到消费者后,标记这条消息为已经被消费,但是这种方式无法很好地保证消费的处理语义

    image-20220708152342102

13.2.2 发布订阅消息传递

  1. 理解

    • 在发布-订阅消息系统中,消息被持久化到一个topic中
    • 在发布-订阅消息系统中,消息的生产者称为发布者,消费者称为订阅者
  2. 特点

    • 消费者可以订阅一个或多个topic,消费者可以消费该topic中所有的数据,同一条数据可以被多个消费者消费,数据被消费后不会立马删除
  3. 应用

    • Kafka 采取拉取模型(Poll),由自己控制消费速度,消费者可以按照任意的偏移量进行消费

    image-20220708152718659

13.3 Kafka简介

13.3.1 Kafka介绍

  1. 定义理解

    • Kafka传统定义:Kafka是一个分布式的基于发布/订阅模式的消息队列(MessageQueue),主要应用于大数据实时处理领域。
    • Kafka最新定义:Kafka是一个开源的分布式事件流平台(Event StreamingPlatform),被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用。
    • Kafka其他定义:Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据
    • 发布/ 订阅:订阅:消息的发布者不会将消息直接发送给特定的订阅者,而是将发布的消息分为不同的类别,订阅者只接收感兴趣的消息。
  2. 消息队列

    • 消息队列是一种进程间通信或者同一个进程中不同线程间的通信方式,主要解决异步处理应用耦合、流量消峰等问题,实现高性能、高可用、可伸缩和最终一致性架构,是大型分布式系统不可缺少的中间件

    image-20220708161557973

  3. 本质

    • Kafka 本质上是一个 消息队列MQ(Message Queue),

    • 使用消息队列的好处(面试)

      • 解耦:允许我们独立的扩展或修改队列两边的处理过程。

      • 可恢复性:即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

      • 缓冲:有助于解决生产消息和消费消息的处理速度不一致的情况。

      • 灵活性&峰值处理能力:不会因为突发的超负荷的请求而完全崩溃,消息队列能够使关键组件顶住突发的访问压力。

      • 异步通信:消息队列允许用户把消息放入队列但不立即处理它

  4. 应用

    • Kafka 用于离线和在线消息的消费,将消息数据按顺序保存在磁盘上,并在集群内以副本的形式存储以防止数据丢失。Kafka 可以依赖 ZooKeeper 进行集群管理,并且受到越来越多的分布式处理系统的青睐,比如 Storm、Spark、Flink 等都支持与 Kafka 集成,用于实时流式计算

13.3.2 设计目标

  1. 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能。
  2. 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条消息的传输。
  3. 支持Kafka Server间的消息分区,及分布式消费,同时保证每个partition内的消息顺序传输。
  4. 同时支持离线数据处理和实时数据处理。
  5. 支持在线水平扩展

13.3.3 kafka的优点

  1. 解耦
    在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

  2. 冗余
    有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。

  3. 扩展性
    因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。扩展就像调大电力按钮一样简单。

  4. 灵活性&峰值处理能力
    在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。

  5. 可恢复性
    系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

  6. 顺序保证
    在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。Kafka保证一个Partition内的消息的有序性。

  7. 缓冲

    在任何重要的系统中,都会有需要不同的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行——写入队列的处理会尽可能的快速。该缓冲有助于控制和优化数据流经过系统的速度。

  8. 异步通信
    很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

13.4 Kafka系统架构

image-20220708103714722

名词 解释

  • Producer
    • 消息生产者,就是向 Kafka broker发消息的客户端。
  • Consumer
    • 消息消费者,向 Kafka broker 取消息的客户端。
  • Consumer Group (CG )
    • 消费者组,由多个 consumer组成。 消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个 组内 消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即 消费者组是逻辑上的一个订阅者。
  • Broker
    • 一台 Kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个broker可以容纳多个 topic。
  • Topic
    • 可以理解为一个队列, 生产者和消费者面向的都是一个 topic。
  • Partition
    • 为了实现扩展性,一个非常大的 topic 可以分布到多个 broker(即服务器)上,一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列。
  • Replica
    • 副本。一个 topic 的每个分区都有若干个副本,一个 Leader 和若干个Follower。
  • Leader
    • 每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是 Leader。
  • Follower
    • 每个分区多个副本中的“从”,实时从 Leader 中同步数据,保持和Leader 数据的同步。Leader 发生故障时,某个 Follower 会成为新的 Leader。

13.4.1 Broker

  1. 理解

    • Kafka集群包含一个或多个服务器,服务节点称为broker
    • 一个独立的kafka服务器被称为broker。
    • 同一个 Topic 的消息可以分布在多个 broker 中;
  2. 作用

    • broker接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。
    • broker为消费者提供服务,对读取分区的请求作出相应,返回已经提交到磁盘上的消息
  3. kafka集群

    • 交给同一个zookeeper集群来管理的broker节点就组成了kafka的集群。
    • broker是集群的组成部分,每个集群都有一个broker同时充当集群控制器的角色。控制器负责管理工作,包括将分区分配给broker和监控broker。在broker中,一个分区从属于一个broker,该broker被称为分区的首领。一个分区可以分配给多个broker(Topic设置了多个副本的时候),这时会发生分区复制

    image-20220708171732030

13.4.2 Topic

  1. 理解

    • 每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic
    • 类似于数据库的Table,
  2. 物理和逻辑上的理解

    • 物理上不同的Topic信息分开存储

    • 逻辑上一个Topic的消息虽然存储在一个或多个Broker上,但是用户只需要指定消息的Topic,就可以生产或消费数据而不必关心数据存放在整个集群的哪个broker

      • 为了性能考虑,如果topic内的消息只存于一个broker,那这个broker会成为瓶颈,无法做到水平扩展
    • topic是逻辑的概念,partition是物理的概念,对用户来说是透明的

  3. 创建流程

    • controller在ZooKeeper的/brokers/topics节点上注册watcher,当topic被创建,则controller会通过watch得到该topic的partition/replica分配。
    • controller从/brokers/ids读取当前所有可用的broker列表,对于set_p中的每一个partition:
      • 从分配给该partition的所有replica(称为AR)中任选一个可用的broker作为新的leader,并将AR设置为新的ISR
      • 将新的leader和ISR写入/brokers/topics/[topic]/partitions/[partition]/state
    • controller通过RPC向相关的broker发送LeaderAndISRRequest。
  4. 删除流程

    • 1.controller在zooKeeper的/brokers/topics节点上注册watcher,当topic被删除,则controller会通过watch得到该topic的partition/replica分配。
      2.若delete.topic.enable=false,结束;否则controller注册在/admin/delete_topics上的watch被fire,controller通过回调向对应的broker发送StopReplicaRequest。

13.4.3 Partition

image-20220708104014899

  1. 理解

    • topic中的数据分割为一个或多个partition
    • 每个Topic至少一个partition,当生产者产生数据的时候,根据分配策略,选择分区,然后将消息追加到指定的分区的末尾(队列)
  2. 每条消息都会有一个自增的编号

    • 标识顺序
    • 用于标识消息的偏移量
    • 每个Partition都有自己独立的编号
  3. partition数据

    • 每个partition中的数据使用多个segment文件存储
    • partition内的数据是有序的,partition之间是无序的
    • 如果topic有多个partition,消费数据时就不能保证数据的顺序
      • 严格保证消息的消费顺序的场景下,需要将partition的数目设置为1

对Broker、Topic和Partition之间的联系理解

  1. broker和集群和副本
    broker:一个独立的kafka服务器被称为broker。broker接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。broker为消费者提供服务,对读取分区的请求作出相应,返回已经提交到磁盘上的消息。

    集群:交给同一个zookeeper集群来管理的broker节点就组成了kafka的集群。

    broker是集群的组成部分,每个集群都有一个broker同时充当集群控制器的角色。控制器负责管理工作,包括将分区分配给broker和监控broker。在broker中,一个分区从属于一个broker,该broker被称为分区的首领。一个分区可以分配给多个broker(Topic设置了多个副本的时候),这时会发生分区复制。如下图:

    image-20220708171549171

  2. topic和partition
    Kafka的消息通过主题(Topic)进行分类,就好比是数据库的表,或者是文件系统里的文件夹。主题可以被分为若干个分区(Partition),一个分区就是一个提交日志。消息以追加的方式写入分区,然后以先进先出的顺序读取。注意,由于一个主题一般包含几个分区,因此无法在整个主题范围内保证消息的顺序,但可以保证消息在单个分区内的顺序。主题是逻辑上的概念,在物理上,一个主题是横跨多个服务器的。

    image-20220708172900065

    注意:不能减少分区的数量,因为如果删除了分区,分区里面的数据也一并删除了,导致数据不一致。如果一定要减少分区的数量,只能删除topic重建)
    ————————————————
    版权声明:本文为CSDN博主「wangfy_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/chushoufengli/article/details/114662193

13.4.4 Leader

  1. 理解
    • 每个partition有多个副本,其中有且只有一个作为leader,leader是当前负责数据的读写的partition

13.4.5 Follower

  1. 理解
    • Follower跟随Leader,所有写请求都通过leader路由,数据变更会广播给所有的Flower,Follower与leader保持数据同步
    • 如果Leader失效,会从Follower中选举出一个新的Leader
    • 当Follower挂掉、卡住或者同步太慢,leader会把这个follower从“in sync replicas”(ISR)列表中删除,重新创建一个Follower

13.4.6 Replication

  1. 理解
    • Kafka中的Replication功能是为了给每个partition提供备份,当某个Broker挂掉时可以迅速实现故障切换(failover)
    • 数据会存放到topic的Partation中,但是有可能分区会损坏,我们需要对分区的数据进行备份(备份多少取决于你对数据的重视程度)
  2. 分区分类我们将分区的分为Leader(1)和Follower(N)
    • Leader负责写入和读取数据
    • Follower只负责备份
    • 保证了数据的一致性
  3. 备份数设置为N,表示主+备=N(参考HDFS)

13.4.7 Producer

  1. 理解
    • 生产者,即数据的发布者,该角色将信息发布到Kafka的topic中
    • 生产者发送的消息,存储到一个partition中,生产者也可以指定数据存储的partition
  2. 作用
    • broker接收到生产者发送的消息后,broker将该消息追加到当前用于追加数据的segment文件中

13.4.8 consumer

  1. 理解
    • 消费者可以从broker中读取数据,消费者可以消费多个topic中的数据

13.4.9 Consumer Group

  1. 理解
    • 每个consumer属于一个特定的consumer group可为每个Consumer指定group name,若不指定group name则属于默认的group)
  2. consumer group出现的原因
    • 将多个消费者集中到一起去处理某一个Topic的数据,可以更快的提高数据的消费能力
    • 整个消费组共享一组偏移量(防止数据被重复读取),因为一个topic有多个分区

13.4.10 offset

  1. 理解
    • offset偏移量,可以唯一的标识一条消息
    • 偏移量决定读取数据的位置,不会有线程安全的问题,消费者通过偏移量来决定下次读取的消息
  2. 读取消息后的处理
    • 消息被消费之后,并不会立马删除,这样多个业务就可以重复使用kafka的消息
    • 我们某一个业务也可以通过修改偏移量达到重新读取消息的目的,偏移量由用户控制
    • 消息最终还是会被删除的,默认生命周期是7天

13.4.11 Zookeeper

  1. 理解

    • kafka 通过 zookeeper 来存储集群的 meta 信息
  2. Kafka中Zookeeper的节点

    image-20220708175956910

13.4.12 Kafka的拓扑结构图

版本一:

image-20220708180944122

版本二:

image-20220708181101844

13.5 Kafka环境搭建

  1. 基于Zookeeper搭建并开启
    【123】zkServer.sh start

  2. 配置Kafka

    • 上传解压拷贝

      [root@node01 ~]# tar -zxvf kafka_2.12-0.11.0.3.tgz
      [root@node01 ~]# rm -rf kafka_2.12-0.11.0.3.tgz
      [root@node01 ~]# mv kafka_2.12-0.11.0.3 /opt/yjx/
      [root@node01 ~]# cd /opt/yjx/kafka_2.12-0.11.0.3/config
      
    • 修改配置文件
      [root@node01 config]# vim server.properties

      ## 修改
      21 broker.id=0
      35 listeners=PLAINTEXT://192.168.88.101:9092
      63 log.dirs=/var/yjx/kafka-logs
      126 zookeeper.connect=node01:2181,node02:2181,node03:2181
      

13.6 Kafka数据存储

  1. 数据存储理解

    • topic在物理层面以partition为分组,一个topic可以分成若干个partition
    • partition还可以细分为segment,一个partition物理上由多个segment组成
      • segment参数有两个
      • log.segment.bytes:单个segment可容纳的最大数据量,默认为1GB
      • log.segment.ms:Kafka在commit一个未写满的segment前,所等待的时间(默认为7天)
  2. logsement文件

    • logsegment文件由两部分组成,分别为“.index”文件和“.log”文件,分别表示为 Segment 索引文件和数据文件。
    • partition全局的第一个segment从0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset值
    • 数值大小为64位,20位数字字符长度,没有数字用0填充
    第一个segment
    00000000000000000000.index
    00000000000000000000.log
    第二个segment,文件命名以第一个segment的最后一条消息的offset组成
    00000000000000170410.index
    00000000000000170410.log
    第三个segment,文件命名以上一个segment的最后一条消息的offset组成
    00000000000000239430.index
    00000000000000239430.log
    
  3. 消息的物理结构

    • 消息都具有固定的物理结构,包括:offset(8 Bytes)、消息体的大小(4 Bytes)、crc32(4 Bytes)、magic(1 Byte)、attributes(1 Byte)、key length(4 Bytes)、key(K Bytes)、payload(N Bytes)等等字段,可以确定一条消息的大小,即读取到哪里截止

    image-20220708192840114

    • .index文件存储大量的索引信息,.log 文件存储大量的数据,索引文件中的元数据指向对应数据文件中的Message的物理偏移量
  4. 其他文件

    • .index 位移索引

    image-20220708193112031

    • .timeindex 时间戳索引

    image-20220708193134495

    • .snapshot 文件,记录了producer的事务信息。

    image-20220708193233935

13.7 Kafka生产者数据安全

13.7.1 数据分区

  1. 分区原因

    • 方便在集群中扩展,每个partition可以通过调整以适应它所在的机器
    • 一个topic可以有多个partition组成,因此可以以partition为单位读写
    • 可以提高并发,
    • Kafka可以将主题划分为多个分区(Partition),会根据分区规则选择把消息存储到哪个分区中,只要如果分区规则设置的合理,那么所有的消息将会被均匀的分布到不同的分区中,这样就实现了负载均衡和水平扩展。另外,多个订阅者可以从一个或者多个分区中同时消费数据,以支撑海量数据处理能力
  2. 分区原则

    • 将producer发送的数据封装成一个producerRecord对象,对象包含:
      • topic:string 类型,NotNull。
      • partition:int 类型,可选。
      • timestamp:long 类型,可选。
      • key:string 类型,可选。
      • value:string 类型,可选。
      • headers:array 类型,Nullable。

13.7.2 数据可靠性保证

1. ACK机制

为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,都需要向producer发送ack(acknowledgement确认收到),如果producer收到ack,就会进行下一轮的发送,否则重新发送数据。

2. ACK时机
  1. 部分 Follower 与 Leader 同步完成,Leader 发送 ACK

  2. 全部 Follower 与 Leader 同步完成,Leader 发送 ACK

  3. Leader的选举过程

    • Leader维护了一个动态的 in-sync replica set(ISR 和 Leader 保持同步的 Follower 集合),当 ISR 集合中的 Follower 完成数据的同步之后,Leader 就会给 Follower 发送 ACK
    • 如果 Follower 长时间未向 Leader 同步数据,则该 Follower 将被踢出 ISR 集合,判断标准:
      • 超过10秒钟没有同步数据
        replica.lag.time.max.ms=10000
      • 主副节点差4000条数据
        rerplica.lag.max.messages=4000
    • Leader 发生故障后,就会从 ISR 中选举出新的 Leader
      • kafka采用一种降级措施来处理:选举第一个恢复的node作为leader提供服务,以它的数据为基准,这个措施被称为脏leader选举
  4. ISR和AR的理解

    • AR(Assigned Replicas):一个分区中所有的副本统称为AR
    • ISR(In-Sync Replicas):Leader副本和所有保持一定程度同步的Follower副本(包括Leader本身)组成ISR
    • OSR(Out-of-Sync Raplicas):与 ISR 相反,没有与 Leader 副本保持一定程度同步的所有Follower 副本组成OSR;
    • 首先,生产者会将消息发送给 Leader 副本,然后 Follower 副本才能从 Leader 中拉取消息进行同步,在同一时刻,所有副本中的消息不完全相同,也就是说同步期间,Follower 相对于 Leader 而言会有一定程度上的滞后,当然这个滞后程度是可以通过参数来配置的。
    • AR = ISR + OSR
    Leader 负责维护和跟踪 ISR 集合中所有 Follower 副本的滞后状态,当 Follower 出现滞后太多或者失效时,Leader 将会把它从 ISR 集合中剔除。
    
    当然,如果 OSR 集合中有 Follower 同步范围追上了 Leader,那么 Leader 也会把它从 OSR 集合中转移至 ISR 集合。
    
    一般情况下,当 Leader 发送故障或失效时,只有 ISR 集合中的 Follower 才有资格被选举为新的 Leader,而 OSR 集合中的 Follower 则没有这个机会(不过可以修改参数配置来改变)
    
3. ACK应答机制

Kafka 为用户提供了三种可靠性级别,用户根据可靠性和延迟的要求进行权衡,Producers可以选择是否为数据的写入接收ack,有以下几种ack的选项:request.required.acks

  1. acks=0;
    • 这意味着 Producer 无需等待来自 Leader的确认而继续发送下一批消息
    • 当 Broker 故障时有可能丢失数据
  2. acks=1
    • Producer 在 ISR 中的 Leader 已成功收到的数据并得到确认后发送下一条 Message
    • 如果在 Follower 同步成功之前 Leader 故障,那么将会丢失数据
  3. acks=-1
    • Producer 需要等待 ISR 中的所有 Follower 都确认接收到数据后才算一次发送完成,可靠性最高
    • 在 Broker 发送 ACK 时,Leader 发生故障,则会造成数据重复
4. 故障处理

image-20220708202157641

  1. 对于HW和LEO的理解

    • LEO

      • 标识当前日志中已写入消息的最后一条的下一条待写入的消息offset(如下图的offset为9的位置就是当前日志文件的LEO)
      • LEO的大小相当于当前日志分区中最后一条消息的offset值加1
    • HW高水位

      • 所有副本中最小的LEO,一个分区中所有副本最小的offset,取一个partition对应的ISR中最小的LEO作为HW
      • 标识了一个特定的消息偏移量(offset),消费者只能拉取到这个offset之前的消息(HW所在的位置上一条信息)

      image-20220708203902228

  2. Follower故障

    • Follower 发生故障后会被临时踢出 ISR 集合,待该 Follower 恢复后,Follower 会 读取本地磁盘记录的上次的 HW,并将 log 文件高于 HW 的部分截取掉,从 HW 开始向 Leader 进行同步数据操作
    • 等该 Follower 的 LEO 大于等于该 Partition 的 HW,即 Follower 追上 Leader 后,就可以重新加入 ISR 了
  3. Leader 故障:

    • Leader 发生故障后,会从 ISR 中选出一个新的 Leader,之后,为保证多个副本之间的数据一致性,其余的 Follower 会先将各自的 log 文件高于 HW 的部分截掉,然后从新的 Leader 同步数据。
    • 如果一个partition所有的replica(副本,包括leader)都发生故障(相关的Broker均掉线),目前Kafka的策略是第一个重新恢复工作的replica默认为leader, 尽管有可能不属于原来的ISR
    • 未来Kafka希望能通过配置满足使用场景对于down机和dataloss的不同关切程度,也就是说如果使用方需要保证数据不丢失,可以选择等待原有ISR中的replica复活作为Leader。代价是down机时间可能更长。
    • 注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。
5. Exactly Once 语义

在分布式系统中,构成系统的任何节点都是被定义为可以彼此独立失败的。比如在 Kafka中,broker可能会crash,在producer推送数据至topic的过程中也可能会遇到网络问题。根据producer处理此类故障所采取的提交策略类型,我们可以获得不同的语义:

  1. 至少一次(at-least-once):
    • 消息不会丢失,但有可能被重复发送。
    • 如果producer收到来自Kafka broker的确认(ack)或者acks = all,则表示该消息已经写入到Kafka。但如果producer ack超时或收到错误,则可能会重试发送消息,客户端会认为该消息未写入Kafka。如果broker在发送Ack之前失败,但在消息成功写入Kafka之后,此重试将导致该消息被写入两次,因此消息会被不止一次地传递给最终consumer,这种策略可能导致重复的工作和不正确的结果。
  2. 最多一次(at-most-once):
    • 消息可能会丢失,但绝不会被重复发送。
    • 如果在ack超时或返回错误时producer不重试,则该消息可能最终不会写入Kafka,因此不会传递给consumer。在大多数情况下,这样做是为了避免重复的可能性,业务上必须接收数据传递可能的丢失。
  3. 精确一次(exactly-once):
    • 消息不会丢失,也不会被重复发送。
    • 即使producer重试发送消息,消息也会保证最多一次地传递给最终consumer。该语义是最理想的,但也难以实现,这是因为它需要消息系统本身与生产和消费消息的应用程序进行协作。例如如果在消费消息成功后,将Kafka consumer的偏移量rollback,我们将会再次从该偏移量开始接收消息。这表明消息传递系统和客户端应用程序必须配合调整才能实现excactly-once。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值