文章目录
消息队列
什么是消息队列
我们可以把消息队列比作是一个存放消息的容器,当我们需要使用消息的时候可以取出消息供自己使用。
消息队列优点
- 解耦:允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束
- 可恢复性:系统的一部分组件失效时,不会影响到整个系统
- 缓冲: 有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况
- 灵活性&削峰: 使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃
- 异步通信: 消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它
消息队列模式
点对点模式
一对一,消费者主动拉取数据,消息收到后消息清除
发布/订阅模式
- 一对多,消费者消费数据之后不会清除消息
- 同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到 topic 的消息会被所有订阅者消费
- kafka采用该模式
kafka
什么是kafka
Kafka 是一个分布式的基于发布/订阅模式的消息队列(Message Queue)
kafka基础架构
- Broker:一台 kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个 broker可以容纳多个 topic
- Producer:消息生产者,就是向 kafka broker 发消息的客户端
- Consumer:消息消费者,向 kafka broker 取消息的客户端
- Consumer Group (CG): 消费者组,由多个 consumer 组成。 消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费;消费者组之间互不影响。 所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者
- Topic:可以理解为一个队列, 生产者和消费者面向的都是一个 topic
- Partition: 分区,为了实现扩展性,一个非常大的 topic 可以分布到多个 broker(即服务器)上,一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列
- Replica: 副本,为保证集群中的某个节点发生故障时, 该节点上的 partition 数据不丢失,且 kafka 仍然能够继续工作,kafka 提供了副本机制,一个 topic 的每个分区都有若干个副本,一个 leader 和若干个 follower
- leader: 每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是 leader
- follower:每个分区多个副本中的“从”,实时从 leader 中同步数据,保持和 leader 数据的同步。 leader 发生故障时,某个 follower 会成为新的 follower
kafka生产者
分区策略
分区原因
- 方便在集群中扩展
- 提高并发
分区原则
- 指明 partition 的情况下,直接将指明的值直接作为 partiton 值
- 没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition数进行取余得到partition 值
- 既没有 partition 值又没有 key 值的情况下,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与 topic 可用的 partition 总数取余得到 partition值,也就是常说的 round-robin 算法
数据可靠性保证
为保证 producer 发送的数据,能可靠的发送到指定的 topic, topic 的每个 partition 收到producer 发送的数据后, 都需要向 producer 发送 ack(acknowledgement 确认收到) ,如果producer 收到 ack, 就会进行下一轮的发送,否则重新发送数据
副本同步策略
方案一
半数以上完成同步, 就发送 ack
- 优点: 低延迟
- 缺点:选举新的 leader 时, 容忍 n 台节点的故障,需要 2n+1 个副本
方案二(kafka采用)
全部完成同步,才发送ack
- 优点: 选举新的 leader 时,容忍 n 台节点的故障,需要 n+1 个副本
- 缺点: 高延迟
kafka选用方案2原因
同样为了容忍 n 台节点的故障,第一种方案需要 2n+1 个副本,而第二种方案只需要 n+1个副本,而 Kafka 的每个分区都有大量的数据, 第一种方案会造成大量数据的冗余,且网络延迟对 Kafka 的影响较小
ISR
Leader 维护了一个动态的 in-sync replica set (ISR),意为和 leader 保持同步的 follower 集合。当 ISR 中的 follower 完成数据的同步之后, leader 就会给 follower 发送 ack。如果 follower长 时 间 未 向 leader 同 步 数 据 , 则 该 follower 将 被 踢 出 ISR , 该 时 间 阈 值 由replica.lag.time.max.ms 参数设定。 Leader 发生故障之后,就会从 ISR 中选举新的 leader
ACK(acknowledgement 确认收到)
应答机制
对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等 ISR 中的 follower 全部接收成功
ACK三种可靠性级别
-
ack=0: producer 不等待 broker 的 ack
- 优点: 最低延迟,可以保证生产者每条消息只会被发送一次(即At Most Once 语义:保证数据不重复,但是不能保证数据不丢失)
- 缺点: broker 一接收到还没有写入磁盘就已经返回,当 broker 故障时有可能丢失数据
-
ack=1: producer 等待 broker 的 ack, partition 的 leader 落盘成功后返回 ack
- 缺点: broker 一接收到还没有写入磁盘就已经返回,当 broker 故障时有可能丢失数据
-
ack=-1(all) : producer 等待 broker 的 ack, partition 的 leader 和 follower 全部落盘成功后才返回 ack
-
优点: 保证 Producer 到 Server 之间不会丢失数据(即At Least Once 语义:保证数据不丢失,但是不能保证数据不重复)
-
缺点: 如果在 follower 同步完成后, broker 发送 ack 之前, leader 发生故障,那么会造成数据重复
将服务器的 ACK 级别设置为-1,可以保证 Producer 到 Server 之间不会丢失数据,即 At
Least Once 语义。相对的,将服务器 ACK 级别设置为 0,可以保证生产者每条消息只会被
发送一次,即 At Most Once 语义。
At Least Once 可以保证数据不丢失,但是不能保证数据不重复;相对的,At Least Once
可以保证数据不重复,但是不能保证数据不丢失。但是,对于一些非常重要的信息,比如说
交易数据,下游数据消费者要求数据既不重复也不丢失,即 Exactly Once 语义
-
Exactly Once 语义
Exactly Once语义0.11版本kafka后支持
At Least Once + 幂等性 = Exactly Once
幂等性
- 定义: 指 Producer 不论向 Server 发送多少次重复数据, Server 端都只会持久化一条
- 原理: 将原来下游需要做的去重放在了数据上游;开启幂等性的 Producer 在初始化的时候会被分配一个 PID,发往同一 Partition 的消息会附带 Sequence Number。而Broker 端会对<PID, Partition, SeqNumber>做缓存,当具有相同主键的消息提交时, Broker 只会持久化一条
- 如何启用幂等性: 只需要将 Producer 的参数中 enable.idompotence 设置为 true 即可
- 局限性: PID 重启就会变化,同时不同的 Partition 也具有不同主键,所以幂等性无法保证跨分区跨会话的 Exactly Once
kafka消费者
消费方式
push模式
即由消息生产者
主动推送生产的数据
- 优点: 可以以最快速度传递消息
- 缺点: 很容易造成 消费者 来不及处理消息,造成拒绝服务以及网络拥塞等问题
pull模式(kafka采用)
即由消费者
主动来获取数据
- 优点:可以根据消费者的消费能力以适当的速率消费消息
- 缺点:如果 kafka 没有数据,消费者可能会陷入循环中,一直返回空数据、
- 解决方案: kafka 的消费者在消费数据时会传入一个时长参数 timeout,如果当前没有数据可供消费,consumer 会等待一段时间之后再返回,这段时长即为 timeout