Kafka学习记录

简介

Kafka 是一个分布式的( distributed )、多分区的( partitioned )、多副本的( plicated )、提交日志( commitlog )的消息流服务。

“分布式”是所有分布式系统的特性 ;

“分区”指消息会按照分区分布在集群的所有节点上;

“副本”指每个分区都会有多个副本存储在不同的节点上;

“提交日志”指新的消息总是以追加的方式进行存储。

而Kafka直接使用提交日志作为最终的存储格式。

 

一、基本概念

节点:Broker,一个 kafka 实例,称为一个节点。

集群:Cluster,由一组 kafka 节点组成的节点群。

分区:Partition,消息的存储空间,每个 topic 将被分成多个(区)。(用于扩展,和 并行处理)

副本:Replication,partition 的备份。(用于容错)

片段:Segment,partition 物理上由多个 segment 组成,每个 segment 存着 index 信息和 message 信息。

消息:Message,在消费者和生产者之间传递的数据流。

主题 :Topic,通过对消息指定主题可以将消息分类,消费者可以只关注自己需要的 topic 中的消息。

生产者:Producer,向 kafka 集群发送消息,在发送消息之前,会对消息进行分类,即 topic。

消费者:Consumer,消费者通过与 kafka 集群建立长连接的方式,不断地从集群中拉取消息,然后可以对这些消息进行处理。

分组:Consumer Group,在 kafka 的设计中,可以有多个不同的消费者分组来同时消费同一个 topic 下的消息。

提交日志:Commit log,.log 文件,消息数据存储,存在于segment中。

索引:.index 文件,消息索引,存在于segment中。

偏移量:Offset,在 partition 内的每一条消息都有一个有序的id号,这个id号被称为 offset,它可以唯一确定消息在 partition 中的位置,即 offset 表示 partition 中的第多少条消息。

 

分区的每个副本存储在不同的broker节点上,每个副本都对应一个日志 在将分区存储到底层 文件系统上时,每个分区对应一个目录,

分区目录下有多个日志分段( LogSegment), 同一个目录下, 所有的日志分段都属于 一个分区。

每个日志分段在物理上 由一个数据文件和 一个索引文件组成 ,数据文件存储的是消息的真正内容,

索引文件存储的是数据文件的索引信息 为数据文件建立索引文件的目的是更快地访问数据文件。

 

二、架构

 

 

 

 

三、Zookeeper 在 kafka 的作用

  元数据管理:Broker 注册、Topic 注册、Producer 和 Consumer 负载均衡、维护 Partition 与 Consumer 的关系、记录消息消费的进度以及 Consumer 注册等。

      leader选举:

      集群容错:

 

四、运行原理

Kafka 的大致工作模式:

1、启动 ZooKeeper 的 server

2、启动 Kafka 的 server,即 Broker

3、Producer 生产数据,然后通过 ZooKeeper 找到 Broker,再将数据 push 到 Broker 保存

4、Consumer 通过 ZooKeeper 找到 Broker,然后再主动 pull 数据

  

五、核心机制

broker controller选举:

  broker 启动或者旧的 controller 故障后,最先写成功 Zookeeper 中 /controller临时节点 数据的 broker 即成为新的 controller。

  • 从Zookeeper中读取当前分区的所有ISR(in-sync replicas)集合
  • 调用配置的分区选择算法选择分区的leader

 

分区分配策略;

分区的 leader 选举:

  controller会将leader的改变直接通过RPC的方式(比ZooKeeper Queue的方式更高效)通知需为此作为响应的Broker。不使用 zookeeper,避免 脑裂,羊群效应,zookeeper watch负载过高问题。

  分区leader选择算法:

  • NoOpLeaderSelector–偏爱分区(SR中的第一个),并将leader发送给为此做出改变的broker,
  • OfflinePartitionLeader–也是选择偏爱分区作为leader
  • ReassignedPartitionLeader
  • PreferredReplicaPartitionLeader
  • ControlledShutdownLeader

副本同步机制:LEO,HW

ISR机制:IN-SYNC Replication。ISR(同步副本集合), 维护了与 leader 信息一致的 follower 副本的信息,当 leader 挂掉的时候 就从这个 ISR 中选举新的 leader 。

文件存储机制:.log文件, .index 文件,稀疏索引,二分法

分片算法:hash取余 ?

限流机制:Quota 参数设置

consumer 心跳机制:

Kafka是通过心跳机制来控制超时,心跳机制对于消费者客户端来说是无感的,它是一个异步线程,当我们启动一个消费者实例时,心跳线程就开始工作了。

在org.apache.kafka.clients.consumer.internals.AbstractCoordinator中会启动一个HeartbeatThread线程来定时发送心跳和检测消费者的状态。

每个消费者都有个org.apache.kafka.clients.consumer.internals.ConsumerCoordinator,

而每个ConsumerCoordinator都会启动一个HeartbeatThread线程来维护心跳,心跳信息存放在org.apache.kafka.clients.consumer.internals.Heartbeat中。

 

幂等性:ProducerID和SequenceNumber

ProducerID:在每个新的Producer初始化时,会被分配一个唯一的ProducerID,这个ProducerID对客户端使用者是不可见的。

SequenceNumber:对于每个ProducerID,Producer发送数据的每个Topic和Partition都对应一个从0开始单调递增的SequenceNumber值。

事务:

  Kafka中的事务与数据库的事务类似,Kafka中的事务属性是指一系列的Producer生产消息和消费消息提交Offsets的操作在一个事务中,即原子性操作。对应的结果是同时成功或者同时失败。

  对Kafka来说,操作事务是指一系列的生产和消费等原子性操作。 

 

 

控制器 - Controller

控制器,负责集群管理和协调,分区状态管理,副本状态管理。

 

更新集群元数据信息。

创建 topic。

删除 topic。

分区重分配。

preferred leader 副本选举。

topic 分区扩展。

broker 加入集群。

broker 崩溃。

受控关闭。

controller leader选举。

 

分区及副本分配

目标

  • 在brokers之间均分replicas
  • partition与它的其他replicas不再同一个broker上
  • 如果broker有rack信息,则partition的replicas尽量分配在不同rack上面

 

算法

  • 一种是rack unware
  • 一种是rack-ware

 

分区分配

1、producer -> 分区

2、broker -〉分区

3、consumer -> 分区

  • RangeAssignor分配策略;
  • RoundRobinAssignor分配策略;
  • StickyAssignor分配策略

 

Leader 选举

 

副本同步机制

所谓同步,必须满足如下两个条件:

  • 副本节点必须能与zookeeper保持会话(心跳机制)
  • 副本能复制leader上的所有写操作,并且不能落后太多。(卡住或滞后的副本控制是由 replica.lag.time.max.ms 配置)

ISR机制

Kafka的复制机制既不是完全的同步复制,也不是单纯的异步复制。

事实上,同步复制要求所有能工作的follower都复制完,这条消息才会被commit,这种复制方式极大的影响了吞吐率。

而异步复制方式下,follower异步的从leader复制数据,数据只要被leader写入log就被认为已经commit,这种情况下如果follower都还没有复制完,落后于leader时,突然leader宕机,则会丢失数据。

而Kafka的这种使用ISR的方式则很好的均衡了确保数据不丢失以及吞吐率。

副本不同步的异常情况:

  • 慢副本:在一定周期时间内follower不能追赶上leader。最常见的原因之一是I / O瓶颈导致follower追加复制消息速度慢于从leader拉取速度。
  • 卡住副本:在一定周期时间内follower停止从leader拉取请求。follower replica卡住了是由于GC暂停或follower失效或死亡。
  • 新启动副本:当用户给主题增加副本因子时,新的follower不在同步副本列表中,直到他们完全赶上了leader日志。

 

文件存储机制

稀疏索引、二分法

通过offset查找message

1、使用offset 通过二分法定位对应的.index文件和.log 文件。

2、通过 .log文件顺序查找到对应的offset偏移对应的消息。

 

数据可靠性和一致性保证

ISR机制;

request.required.acks 参数;

min.insync.replicas 参数。

 

类似 PacificA 算法。

 

 

kafka消息传递语义

消息传递保障

  • At most once: 消息可能会丢,但绝不会重复传输
  • At least once:消息绝不会丢,但可能会重复传输
  • Exactly once:每条消息肯定会被传输一次且仅传输一次

消息去重

  • 业务端去重

 

六、高性能

顺序读写、

page cache、

零拷贝:senfile。

 

page cache

用作缓存磁盘文件的内存就叫做page cache。

  CPU如果要访问外部磁盘上的文件,需要首先将这些文件的内容拷贝到内存中,由于硬件的限制,从磁盘到内存的数据传输速度是很慢的,

如果现在物理内存有空余,可以用这些空闲内存来缓存一些磁盘的文件内容,这部分用作缓存磁盘文件的内存就叫做page cache。 

  用户进程启动read()系统调用后,内核会首先查看page cache里有没有用户要读取的文件内容,如果有(cache hit),那就直接读取,

没有的话(cache miss)再启动I/O操作从磁盘上读取,然后放到page cache中,下次再访问这部分内容的时候,就又可以cache hit,不用忍受磁盘的龟速了(相比内存慢几个数量级)。 

和CPU里的硬件cache是不是很像?两者其实都是利用的局部性原理,只不过硬件cache是CPU缓存内存的数据,而page cache是内存缓存磁盘的数据,这也体现了memory hierarchy分级的思想。 

相对于磁盘,内存的容量还是很有限的,所以没必要缓存整个文件,只需要当文件的某部分内容真正被访问到时,再将这部分内容调入内存缓存起来就可以了,

这种方式叫做demand paging(按需调页),把对需求的满足延迟到最后一刻,很懒很实用。

 

七、消息可靠性保障(消息数据不丢失)

1、生产端:重试机制 + ACK(acknowledge)

2、服务端:多副本

3、消费端:手动提交

 

ACKS

配置生产端 ACK

当 producer 向 leader 发送数据时,可以通过 request.required.acks 参数以及 min.insync.replicas 设置数据可靠性的级别。

  • 当 acks = 1时(默认值),生产者在 ISR 中的 leader 已成功收到数据可以继续发送下一条数据。如果 leader 宕机,由于数据可能还未来得及同步给其 follower,则会丢失数据。
  • 当 acks = 0时,生产者不等待来自 broker 的确认就发送下一条消息。这种情况下数据传输效率最高,但数据可靠性确最低。
  • 当 acks = -1或者 all 时,生产者需要等待 ISR 中的所有 follower 都确认接收到消息后才能发送下一条消息,可靠性最高。

 

  即使按照上述配置 ACK,也不能保证数据不丢,例如,当 ISR 中只有 leader 时(ISR 中的成员由于某些情况会增加也会减少,最少时只剩一个 leader),

此时会变成 acks = 1的情况。所以需要同时在配合 min.insync.replicas 参数(此参数可以在消息队列 CKafka 控制台 Topic 配置开启高级配置中进行配置),

min.insync.replicas 表示在 ISR 中最小副本的个数,默认值是1,当且仅当 acks = -1或者 all 时生效。

 

建议配置的参数值

此参数值仅供参考,实际数值需要依业务实际情况而定。

  • 重试机制:message.send.max.retries=3;retry.backoff.ms=10000;
  • 高可靠的保证:request.required.acks=-1;min.insync.replicas=2;
  • 高性能的保证:request.required.acks=0;
  • 可靠性+性能:request.required.acks=1;

 

 

八、消息分发模型 - Kafka 发布消息时如何选择 Partition

Kafka 默认(当 key 为 null) 时采用 Round-robin 策略。

但我们实际应用中为保持相关消息按序到,就必须送到指定的 Partition,方法可以有:

  • 指定 Partition 编号
  • 指定 Key
  • 自定义 Partitioner - 实现 org.apache.kafka.clients.producer.Partitioner, 并通过属性注册

 

消息发送模式:

发后即忘、同步、异步。 

 

九、再均衡的发生过程

一句话:为消费者分配分区

Kafka中消费者以消费组的形式存在,消费组来消费每个主题中分区的数据,因为主题中的分区数和消费者数量并不一一对应,

这时候就涉及到如何为每个消费者分配分区,而当有消费者在中途退出时,就会触发再均衡的发生,再重新为剩余的消费者分配分区。

每个消费组在服务端对应一个GroupCoordinator对其进行管理,而消费者客户端中的ConsumerCoordinator组件负责与GroupCoordinator进行交互,

它们负责执行分区的分配,以及消费者再均衡的操作。


目前在以下几种情况会触发再均衡操作。

  • 有新的消费者加入消费组。
  • 消费者宕机下线。消费者并不一定需要真正下线,例如遇到长时间的GC、网络延迟等情况,导致消费者长时间未向GroupCoordinator 发送心跳,GroupCoordinator认为消费者已经下线。
  • 有消费者主动退出消费组。
  • 消费组所对应的GroupCoorinator 节点发生了变更。
  • 消费组内所订阅的任一主题或者主题的分区数量发生变化。

 

再均衡时 cousumer 停止工作。

 

十、kafka扩容

1、新增节点

2、生成重新分配topic的方案

3、执行分配方案

4、查看分配进度、状态

注意:需要手动执行

 

十一、高级应用

注意:以下大部分功能原生不支持,需要定制开发。 

过期时间(TTL)

延时队列

死信队列

重试队列

消息路由

消息轨迹

消息审计

消息代理(proxy)

 

十二、其他

副本同步

ISR(in-sync replicas):同步副本集合,只有 ISR 里的成员才有被选为 Leader 的可能。

OSR(Outof-sync replicas):

AR(Assigned Replicas):所有副本的总和。

AR = ISR + OSR

HW(HighWatermark):高水位。一个partition中的ISR列表中,leader的HW是所有ISR列表里副本中最小的那个的LEO。代表partition中已提交可消费的最大offset。

LEO(log end offset):日志末端位移,代表日志文件中下一条待写入消息的offset,这个offset上实际是没有消息的。

 

 

重要参数

request.required.acks:消息发送成功确认方式。

min.insync.replicas:设定ISR中的最小副本数是多少,默认值为1,当且仅当request.required.acks参数设置为-1时,此参数才生效。可以在broker或者topic层面进行设置。

offsets.topic.replication.factor:副本因子,最小写入副本数的个数,partition 副本数。数据冗余备份数。

unclean.leader.election.enable:ISR 副本同步列表 参与选举参数。

producer.type=sync:消息生产模式,同步模式,异步模式。

 

安装部署

  kafka需要java运行环境,以前的kafka还需要zookeeper,新版的kafka已经内置了一个zookeeper环境,所以我们可以直接使用。

 

监控工具

  Kafka Eagle

 

刷盘落盘

  刷盘:pagecache -》硬盘

  落盘:刷盘成功,数据成功写入硬盘

 

参考资料

中文官网

kafka中文教程

Kafka官方文档中文版(还未全部翻译完)

kafka基本设计和原理分析系列

真的,关于 Kafka 入门看这一篇就够了

kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)

简历写了会Kafka,面试官90%会让你讲讲acks参数对消息持久化的影响

Kafka底层原理架构

消息队列之事务消息,RocketMQ 和 Kafka 是如何做的?

kafka实战

kafka客户端java版本

关于kafka-clients JAVA API的基本使用

kafka 配置文件参数详解

Kafka源码系列之源码分析zookeeper在kafka的作用

Kafka 使用 Zookeeper 做什么?

Zookeeper 在 Kafka 中的作用

聊聊kafka的group coordinator

Kafka 0.10 Coordinator概述

kafka-console-consumer.bat 报错 zookeeper is not a recognized option

关于Kafka 的 consumer 消费者手动提交详解

Kafka consumer的offset的提交方式

Spring for Apache Kafka

@KafkaListener通过配置加载多个topic

KafkaListener的各种操作

Kafka 居然还会丢消息?

kafka 如何保证数据不丢失

Kafka优化总结、Kafka数据丢失解决方案、重复消费解决方案

Kafka的存储及刷盘原理

Kafka 之六 connector

kafka connector 使用总结以及自定义connector开发

Kafka 与RocketMQ 落盘机制比较

Kafka的存储及刷盘原理

Linux中的Page Cache [一]

CKafka 数据可靠性说明

【kafka】生产者消息投递可靠性(ACK机制,ISR机制,leader选举机制)

spring-kafka之KafkaListener注解深入解读

SpringBoot中@KafkaListener原理

Kafka 架构中 ZooKeeper 以怎样的形式存在?

Kafka高性能揭秘 —— sequence IO、PageCache、SendFile的应用详解

Kafka 中的再均衡

深入了解Kafka【三】数据可靠性分析

Kafka 概述:深入理解架构

Kafka控制器选举流程剖析

Kafka Partition Leader选举机制原理详解

kafka分区选主机制

KAFKA集群扩容后的数据迁移

posted @ 2019-05-24 15:13  风过无痕521  阅读(204)  评论(0)    收藏  举报