02.kafka基础
# 01.kafka介绍
# 1、Kafka的特性
高吞吐量、低延迟
:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒可扩展性
:kafka集群支持热扩展持久性、可靠性
:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失容错性
:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)高并发
:支持数千个客户端同时读写
# 2、kafka应用场景
1)日志收集
- 一个公司可以用 Kafka 可以收集各种服务的日志数据
- 然后使用 Kafka 提供的功能将这些日志数据统一转发到各种消费者
- 例如 Hadoop、ElasticSearch等进行日志分析
2)消息系统
- Kafka 能够作为一般的消息队列使用,比如 RabbitMQ、ActiveMQ 等,来进行不同系统之间的消息通信
3)用户活动跟踪
- Kafka 也常被用来记录用户的各种在线活动,如浏览网页、搜索、点击等活动
- 这些活动信息被各个服务器发布到 Kafka 的主题(Topic)中
- 然后订阅者就可以订阅这些信息进行用户行为分析
4)运营监控
- Kafka 也可以用来收集各种运营数据,包括收入、指标和各种运营统计数据
- 然后这些数据可以被各种消费者订阅,进行实时的监控和报警
5)流式处理
- 通过 Kafka Stream API,可以处理并分析进入 Kafka 的数据流,比如实时数据分析、ETL等
6)事件源
- Kafka 可以作为(微服务)事件源使用,记录所有系统发生的事件,然后其他微服务可以订阅这些事件进行处理
7)集成和解耦
- Kafka 可以在系统解耦和系统集成中发挥作用
- 生产者和消费者可以独立扩展和演化,降低系统间的耦合度
# 3、Kafka架构组件
Kafka中发布订阅的对象是topic,我们可以为每类数据创建一个topic
把向topic发布消息的客户端称作producer,从topic订阅消息的客户端称作consumer
Producers和consumers可以同时从多个topic读写数据
一个kafka集群由一个或多个broker服务器组成,它负责持久化和备份具体的kafka消息
kakfa主要组件
- topic:消息存放的目录即主题
- Producer:生产消息到topic的一方
- Consumer:订阅topic消费消息的一方(Consumer每消费一个消息,offset加1,简单实现不重复消费)
- Broker:Kafka的服务实例就是一个broker
# 4、Topic&Partition
- 消息发送时都被发送到一个topic,
其本质就是一个目录
,每一个Partition其实都是一个文件
- 每个Partition中的消息都是有序的,生产的消息被不断追加到Partition log上,每个消息都被赋予唯一offset值
- Kafka集群会保存所有的消息,不管消息有没有被消费;
- 我们可以设定消息的过期时间,只有过期的数据才会被自动清除以释放磁盘空间
- Kafka维持的元数据只有–
消费消息在Partition中的offset值
,Consumer每消费一个消息,offset加1
- 消息状态由Consumer控制,Consumer重设offset值,这样Consumer就可以读取任意位置的消息
把消息日志以Partition的形式存放作用
- 第一是方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;
- 第二是可以提高并发,因为可以以Partition为单位读写了
# 02.kafka核心组件
# 1、Producer
Producer: 生产者,发送消息的一方,生产者负责创建消息,然后将其发送到 Kafka
Producer 采用 Push 模式将消息发布到 Kafka Broker,根据负载均衡算法(如轮询、Hash 等)
这些消息将均衡写入到相应 Topic 对应的各个 Partition 中
在存储层面,采用顺序写磁盘(即 Append)模式写入
详细流程如下
1)Producer Push 消息
- 基于
负载均衡算法获得目标 Partition 后
- Producer 先从 ZooKeeper 的
/brokers/.../state
节点找到该 Partition 的 Leader
- 基于
2)Producer 将消息发送给该 Leader
3)Leader 将消息写入本地 Log
4)所有 Follower 主动从 Leader Pull 消息
,写入本地 Log 后向 Leader 发送 ACK
5)Leader ACK
- Leader 收到所有 ISR 中所有 Replica 的 ACK 后
- 更新 HW(High Watermark,最后 Commit 的 Offset),并向 Producer 发送 ACK
6)Producer 接到 ACK,确认发送成功
# 2、Broker
Broker: 服务代理节点,Broker 是 Kafka 的服务节点,即 Kafka 的服务器
- Topic 是逻辑概念,而 Topic 对应的
Partition 则是物理概念
每个 Partition 在存储层面都对应一个文件夹
- 由于 Partition 并不是最终的存储粒度,该
文件夹下还有多个 Segment
消息索引和数据文件
,它们是真正的存储文件
# 3、Consumer
Consumer: 消费者,接受消息的一方,消费者连接到 Kafka 上并接收消息,进而进行相应的业务逻辑处理
目前采用的高级 API,
Consumer 在消费消息时,只需指定 Topic 即可
API 内部实现负载均衡
,并将 Offset 记录到 ZooKeeper 上
值得一提的是,Consumer 采用 Pull 模式从 Broker 中读取数据
这是一种异步消费模式,与 Producer 采用的 Push 模式全然不同
- Push 模式追求速度,越快越好,当然它取决于 Broker 的性能
- 而 Pull 模式则是追求自适应能力,
Consumer 根据自己的消费能力消费
# 4、Consumer Group
一个消费者组可以包含一个或多个消费者
- 使用多分区 + 多消费者方式可以极大提高数据下游的处理速度
同一消费组中的消费者不会重复消费消息
,同样的,不同消费组中的消费者消息消息时互不影响
- Kafka 就是通过消费组的方式来实现消息 P2P 模式和广播模式
# 5、Topic(目录)
- Kafka 中的消息以 Topic 为单位进行划分
- 生产者将消息发送到特定的 Topic,而消费者负责订阅 Topic 的消息并进行消费
# 6、partition(文件)
- 可以简单理解
partition是一个可追加的日志(Log)文件
,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset)
- Kafka中的topic是以partition的形式存放的,
每一个topic都可以设置它的partition数量
,Partition的数量决定了组成topic的log的数量 - Producer在生产数据时,会按照一定规则(这个规则是可以自定义的)把消息发布到topic的各个partition中
- 上面将的副本都是以partition为单位的,不过
只有一个partition的副本会被选举成leader作为读写用
关于如何设置partition值需要考虑的因素
一个partition只能被一个消费者消费
(一个消费者可以同时消费多个partition)因此,如果设置的partition的数量小于consumer的数量,就会有消费者消费不到数据
所以,推荐
partition的数量一定要大于同时运行的consumer的数量
另外一方面,建议
partition的数量大于集群broker的数量
,这样leader partition就可以均匀的分布在各个broker中,最终使得集群负载均衡
# 7、Offset(偏移量)
- offset 是消息在分区中的唯一标识,Kafka 通过它来保证消息在分区内的顺序性
- 不过
offset 并不跨越分区
,也就是说,Kafka 保证的是分区有序性而不是主题有序性
# 8、Replications(副本)
- Kafka
同一 Partition 的数据可以在多 Broker 上存在多个副本
,通常只有主副本对外提供读写服务
- 当主副本所在 broker异常,Kafka 会在 Controller 的管理下会重新
选择新的 Leader 副本对外提供读写服务
- Kafka允许用户为每个topic设置副本数量,副本数量决定了有几个broker来存放写入的数据
- 如果你的
副本数量设置为3
,那么一份数据就会被存放在3台不同的机器上
,那么就允许有2个机器失败 - 一般推荐
副本数量至少为2
,这样就可以保证增减、重启机器时不会影响到数据消费
# 9、controller和Leader
kafka在所有broker中选出一个controller
,所有Partition的Leader选举都由controller决定
- controller会将Leader的改变直接通过RPC的方式通知需为此作出响应的Broker
- 同时controller也负责增删Topic以及Replica的重新分配
leader 负责数据的读写
,而follower只负责数据的读
,如果follower遇到写操作,会提交到leader
# 03.为什么kafka快
# 0、高性能原因
1)零拷贝技术
- Kafka的消费者在消费消息时,不需要将消息从操作系统内核空间拷贝到用户空间
- 而是通过零拷贝技术直接将数据从磁盘读取到网络中,这大大降低了数据读取的开销
2)批量发送和接收
- Kafka的生产者和消费者都支持批量发送和接收消息
3)分区机制
- Kafka的Topic被划分为多个Partition,每个Partition都有Leader副本提供读写
- 这样可以将读写请求均匀地分布到集群中的每个Broker上,提高系统的并行处理能力
4)索引机制
- Kafka为每个Partition的消息创建索引
- 可以通过索引快速定位到消息的位置,提高了数据读取的效率
5)顺序写入
- Kafka将消息以追加的方式写入到磁盘的log文件中
- 这种顺序写的方式可以充分利用硬盘的顺序读写特性,提高磁盘IO的效率
6)写时复制
- 当有新的消息写入时,只需将消息写入Leader副本,然后由Follower副本从Leader副本中拉取数据
- 这样可以避免在写入消息时,需要将消息同时写入到所有副本,减少了写操作的开销
7)消费者拉取
- Kafka的消费者使用拉取模式来消费消息,可以自己控制消费的速度和时间
- 避免了因为消费者处理能力不足,而导致的消息积压问题
8)批量压缩
- Kafka使用了
批量压缩
,即将多个消息一起压缩而不是单个消息压缩
- Kafka使用了
# 1、顺序写入
磁盘读写的快慢取决于你怎么使用它,也就是顺序读写或者随机读写
在顺序读写的情况下,某些优化场景磁盘的读写速度可以和内存持平
因为硬盘是机械结构,每次读写都会寻址->写入,其中寻址是一个“机械动作”,它是最耗时的
为了提高读写硬盘的速度,
Kafka就是使用顺序I/O
每一个Partition其实都是一个文件
,收到消息后Kafka会把数据插入到文件末尾
这种方法有一个缺陷—— 没有办法删除数据 ,所以
Kafka是不会删除数据的
(可以定时清理)
# 2、mmap内存映射
- mmap是一种
将文件或者其它对象映射进内存的一种方法
- 使得
生产者和消费者在进行消息的写入和读取时,都可以直接操作内存
Kafka使用了内存映射文件(Memory Mapped Files)的方式来解决I/O问题(mmap)
通过这种方式,
当程序访问这段内存时,实际上就等于直接在访问对应的文件数据
Kafka的数据并 不是实时的写入硬盘 ,他使用mmap内存映射来进行定期刷入磁盘
Kafka中的mmap主要用在两个地方
- 一是
Producer发送消息
时的消息追加(消息写入操作系统的Page Cache中
) - 二是
Consumer消费消息时
的消息读取(将磁盘数据映射到内存
)
- 一是
在6
4位操作系统
中一般可以表示20G的数据文件
写到mmap中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘
通过mmap,
进程像读写硬盘一样读写内存(当然是虚拟机内存)
,也不必关心内存的大小有虚拟内存为我们兜底
解决mmap写入的不可靠问题,提供的参数
- Kafka提供了一个参数——producer.type来
控制是不是主动flush
- 如果Kafka
写入到mmap
之后就立即flush
然后再返回Producer
叫同步 (sync)
写入mmap
之后立即返回Producer不调用flush
叫异步 (async)
# 3、零拷贝技术
- 零拷贝技术可以
直接将数据从内核缓冲区发送到socket缓冲区,而不需要经过用户缓冲区
- Kafka的Broker端,Broker会使用sendfile系统调用来读取数据
sendfile系统
直接将数据从内核缓冲区(Page Cache)发送到socket缓冲区
(无需复制到用户缓冲区)- 这样,数据在传输过程中就只需要进行一次复制操作,大大提高了数据读取的效率
shendfile文件传输流程
(零拷贝技术)
1)sendfile系统调用,文件数据被copy至
内核缓冲区
2)再从内核缓冲区copy至内核中
socket相关的缓冲区
3)最后再socket相关的缓冲区copy到
协议引擎
注:
- Kafka把所有的消息都存放在一个一个的文件中
- 当消费者需要数据的时候Kafka直接把文件发送给消费者
- 配合mmap作为文件读写方式,直接把它传给sendfile
传统模式下,一个文件进行传输流程
- 1)调用read函数,文件数据被copy到
内核缓冲区
- 2)read函数返回,文件数据从内核缓冲区copy到
用户缓冲区
- 3)write函数调用,将文件数据从用户缓冲区copy到内核与
socket相关的缓冲区
- 4)数据从socket缓冲区copy到
相关协议引擎
# 4、批量压缩
在很多情况下,系统的瓶颈不是CPU或磁盘,而是网络IO
- 如果每个消息都压缩,但是压缩率相对很低,所以Kafka使用了
批量压缩
,即将多个消息一起压缩而不是单个消息压缩 - Kafka允许使用递归的消息集合,批量的消息可以通过压缩的形式传输并且在日志中也可以保持压缩格式,直到被消费者解压缩
- Kafka支持多种压缩协议,包括Gzip和Snappy压缩协议