1、kafka项目背景
- 基本情况
- 开发语言: java、scala
- 管理组织:Apache 基金会、开源
- 主要作用:分布式消息队列
- 基本概念
- topic: 消息按主题(topic)进行分类;
- Partition
- 为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上
- 一个topic可以分为多个partition,每个partition是一个有序的队列
- Kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序
- Offset
- 每条消息在分区(partition)中的唯一编号:每条消息被添加到分区时,都会被分配一个offset,它是消息在分区中的唯一编号,kafka通过offset保证消息在分区内的顺序。
- Partition
- Producer: 消息生成者
- Customer: 消息消费者
- Consumer Group
- 消费者是以consumer group消费者组的方式工作,由一个或者多个消费者组成一个组,共同消费一个topic
- 每个分区在同一时间只能由group中的一个消费者读取,但是多个group可以同时消费这个partition。
- 消费者可以通过水平扩展的方式同时读取大量的消息(通过创建一个group, 就可以同时读取一个topic下多个partition下的数据)。
- 如果一个消费者失败了,那么其他的group成员要负载均衡读取之前失败的消费者读取的分区。
- Consumer Group
- broker: kafka集群中的每个节点
- topic: 消息按主题(topic)进行分类;
- zookeeper在kafka集群中的作用
- Kafka集群依赖于zookeeper集群来保存一些meta信息,并保证系统可用性。
2、消息队列的模式
2.1 点对点模式
- 一对一,消费者主动拉取数据
- 点对点模式通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求信息,而不是将消息推送到客户端。
2.2 发布/订阅模式
- 一对多,数据生产后,发布者推送给所有的订阅者
- 发布订阅模型则是一个基于推送的消息传送模型,发布订阅模型可以有多个不同的订阅者,
- 临时订阅者:只有在主动监听主题时才接受消息
- 持久订阅者:监听主题的所有消息,即使当前订阅者不可用,处于离线状态
3、Kafka 写入数据的设计规则
3.1 选择Partition规则
Topic是一个逻辑上的概念,物理上会被分成多个Partition,每个Partition都可以有多个Replic或者没有。Producer往某个Topic中发送数据的时候,数据会按照一定的规则追加到各个Partition中,选择Partition规则如下
- 指定了Partition,则直接使用;
- 未指定Partition,但存在key,通过key的value进行hash出一个Partition;
- Partition和key都未指定,则使用轮询选出一个Partition。
3.2 Partition中数据的保存
- 采用日志文件夹的方式进行存储
- 每条消息用offset来表示它在分区中的偏移量;
- 同一个Partition中的消息是顺序写的;
- 文件夹命名:<topic_name>_<partition_id>
- Partition 副本
- 通过 server.properties 配置文件中的default.replication.factor=N 进行指定;
- 通过 创建Topic的时候手动指定,1表示没有副本;
3.3 Partition 多副本实现数据高可用
kafka 采用 ISR(In-Sync Replica) 机制结合 HW(High Watermark) 和LED(Log End Offset) 机制实现数据的多备份高可用。
- ISR
- 需要满足的基本条件
- 副本所在的broker必须保持与Zookeeper的连接
- 副本最后一条消息的offset和leader最后一条消息的offset之间的差不能超出指定的阈值
- Partition 多副本实现中leader和follower的信息交互方式
- 每个Partition的Leader会维护本Partition的ISR集合
- 写请求首先由Leader处理
- 之后Follower会从Leader上拉取数据,这个过程会有一定的延迟,所以Follower上的数据会比Leader偏少
- 如果由于网络延迟太大导致Leader和Follower之间相差太多,Follower会被踢出ISR集合
- Follower恢复正常之后会继续与Leader进行同步,当差值再次小于阈值时,Follower会重新加入ISR中。
- 多副本场景Productor写入消息的过程
- producer先从zk的/broker/…/state节点找到该partition的leader
- producer将消息发送给该leader
- leader将消息写入本地log
- followers从leader pull消息,写入本地log后向leader发送ack
- leader 收到所有的followers发送的ack后,向producer发送ack。
- 注意事项
- follewer 只是数据的副本提供数据的可恢复性,本身和kafka 的读写性能无关,==Kafka的读写都只是和leader 相关 ==
- 需要满足的基本条件
- HW(High Watermark))
- HW标记了一个offset,Consumer消费消息的时候只能拉取到HW之前的消息,它由Leader管理。当ISR集合中所有的Follower都拉取HW指定消息进行同步后,Leader会更新HW的值,称这些数据已经‘commit’了。此时即使Leader副本损坏,HW之前的数据也可以在Follower上找到。
- LEO(Log End Offset)
- LEO是指Leader和Follower最后一条记录的offset值。
4、Kafka 消费数据的设计规则
4.1 push 模式(发布订阅模式)
及时推送
- 优点
- 消息推送及时。
- 缺点
- 很难适应消费速率不同的消费者,因为消息发送速率是有broker决定的,他的目标是尽可能以最快速度传递消息
- 很容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络阻塞
4.2 pull 模式(点对点拉取模式)
消费者主动拉取
- 优点
- 简化broker设计,consumer可自主控制消费消息的速率
- consumer可以自己控制消费方式–即可批量消费也可逐条消费
- 缺点
- 如果kafka没有数据,消费者可能会陷入循环中,一直等待数据到达
- 解决方案: 拉请求中设定参数,允许消费者请求在等待数据到达的长轮询中进行阻塞。
- 如果kafka没有数据,消费者可能会陷入循环中,一直等待数据到达