kafka消息队列
Kafka 是⼀个分布式流式处理平台。
Kafka 主要有两⼤应⽤场景:
1. 消息队列 :建⽴实时流数据管道,以可靠地在系统或应⽤程序之间获取数据。
2. 数据处理: 构建实时的流数据处理程序来转换或处理数据流。
Kafka 相⽐其他消息队列主要的优势如下:
1. 极致的性能 :设计中⼤量使⽤了批量处理和异步的思想,最⾼可以每秒处理千万级别的消息。
2. ⽣态系统兼容性⽆可匹敌 :Kafka 与周边⽣态系统的兼容性是最好的没有之⼀,尤其在⼤数据和流计算领域。
消息模型的演变:
1.早期模型:队列
使⽤队列(Queue)作为消息通信载体,满⾜⽣产者与消费者模式,⼀条消息只能被⼀个消费者使⽤, 未被消费的消息在队列中保留直到被消费或超时。 ⽐如:我们⽣产者发送 100 条消息的话,两个消费 者来消费⼀般情况下两个消费者会按照消息发送的顺序各⾃消费⼀半(也就是你⼀个我⼀个的消费。)
假如我们存在这样⼀种情况:我们需要将⽣产者产⽣的消息分发给多个消费者,并且每个消费者都能接 收到完成的消息内容。 这种情况,队列模型就不好解决了。
2.kafka——发布,订阅模型
发布订阅模型(Pub-Sub) 使⽤主题(Topic) 作为消息通信载体,类似于⼴播模式;发布者发布⼀条 消息,该消息通过主题传递给所有的订阅者,在⼀条消息⼴播之后才订阅的⽤户则是收不到该条消息 的。
Kafka 重要的⼏个概念:
1. Producer(⽣产者) : 产⽣消息的⼀⽅。
2. Consumer(消费者) : 消费消息的⼀⽅。
3. Broker(代理) : 可以看作是⼀个独⽴的 Kafka 实例。多个 Kafka Broker 组成⼀个 Kafka Cluster。
每个 Broker 中⼜包含了 Topic 以及 Partition 这两个重要的概念:
Topic(主题) : Producer 将消息发送到特定的主题,Consumer 通过订阅特定的 Topic(主题) 来消费消息。
Partition(分区) : Partition 属于 Topic 的⼀部分。⼀个 Topic 可以有多个 Partition ,并且同⼀ Topic 下的 Partition 可以分布在不同的 Broker 上,这也就表明⼀个 Topic 可 以横跨多个 Broker 。这正如我上⾯所画的图⼀样。
topic和partition是多对多的关系。partition就相当于一个个队列。
kafka多副本机制
分区 (Partition)中的多个副本之间会有⼀个 leader ,其他副本称为 follower。
我们发送的 消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进⾏同步。 ⽣产者和消费者只与 leader 副本交互。
follower只是 leader 副本的拷⻉,它们的存在只是为了保证消息存储的安全性。
当 leader 副本发⽣故障时会从 follower 中选举出⼀个 leader,但是 follower 中如果有和 leader 同步程度达不到要求的参加不了 leader 的竞选。
Kafka 的多分区(Partition)以及多副本(Replica)机制的好处:
1. Kafka 通过给特定 Topic 指定多个 Partition, ⽽各个 Partition 可以分布在不同的 Broker 上, 这样便能提供⽐较好的并发能⼒(负载均衡)。
2. Partition 可以指定对应的 Replica 数, 这也极⼤地提⾼了消息存储的安全性, 提⾼了容灾能 ⼒,不过也相应的增加了所需要的存储空间。
ZooKeeper 主要为 Kafka 提供元数据的管理的功能。
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。
Kafka 如何保证消息的消费顺序?
每次添加消息到 Partition(分区) 的时候都会采⽤尾加法,如上图所示。Kafka 只能为我们保证 Partition(分区) 中的消息有序,⽽不能保证 Topic(主题) 中的 Partition(分区) 的有序。
发送消息的时候指定 key/Partition可以有效解决。
Kafka 如何保证消息不丢失
如果消息发送失败的话,我们检查失败的原因之后重新发送即可! 另外这⾥推荐为 Producer 的 retries (重试次数)设置⼀个⽐较合理的值,⼀般是 3 ,但是为了保证消息不丢失的话⼀般会设置⽐较⼤⼀点。设置完成之后,当出现⽹络问题之后能够⾃动重试消息发送,避免消息丢失。另外,建议还要设置重试间隔,因为间隔太⼩的话重试的效果就不明显了,⽹络波动⼀次你3次⼀下⼦就重试完了。
消费者丢失消息的情况
我们知道消息在被追加到 Partition(分区)的时候都会分配⼀个特定的偏移量(offset)。偏移量 (offset)表示 Consumer 当前消费到的 Partition(分区)的所在的位置。Kafka 通过偏移量 (offset)可以保证消息在分区内的顺序性。
当消费者拉取到了分区的某个消息之后,消费者会⾃动提交了 offset。⾃动提交的话会有⼀个问题, 试想⼀下,当消费者刚拿到这个消息准备进⾏真正消费的时候,突然挂掉了,消息实际上并没有被消费,但是 offset 却被⾃动提交了。
解决办法:每次在真正消费完消息之后之后再⾃⼰⼿动提交 offset 。
但是,这样会带来消息被重新消费的问题。⽐如你刚刚消费完消息之后,还没提交offset,结果⾃⼰挂掉了,那么这个消息理论上就会被消费两次。
Kafka 弄丢了消息
我们知道 Kafka 为分区(Partition)引⼊了多副本(Replica)机制。分区(Partition)中的多个副 本之间会有⼀个叫做 leader 的家伙,其他副本称为 follower。我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进⾏同步。⽣产者和消费者只与 leader 副 本交互。你可以理解为其他副本只是 leader 副本的拷⻉,它们的存在只是为了保证消息存储的安全 性。 试想⼀种情况:假如 leader 副本所在的 broker 突然挂掉,那么就要从 follower 副本重新选出⼀个 leader ,但是 leader 的数据还有⼀些没有被 follower 副本的同步的话,就会造成消息丢失。
解决办法
1,设置 acks = all。acks 是 Kafka ⽣产者(Producer) 很重要的⼀个参数。 acks 的默认值即为1,代表我们的消息被leader副本接收之后就算被成功发送。当我们配置 acks = all 代表则所有副本都要接收到该消息之后该消息才算真正成功被发送。
2,设置 replication.factor = 3 为了保证 leader 副本能有 follower 副本能同步消息,我们⼀般会为 topic 设置 replication.factor =3。这样就可以保证每个 分区(partition) ⾄少有 3 个副本。虽然造成了数据冗余,但是带来了数据的安全性。
3,min.insync.replicas > 1 ⼀般情况下我们还需要设置 min.insync.replicas> 1 ,这样配置代表消息⾄少要被写⼊到 2 个副本 才算是被成功发送。min.insync.replicas 的默认值为 1 ,在实际⽣产中应尽量避免默认值 1。
但是,为了保证整个 Kafka 服务的⾼可⽤性,你需要确保 replication.factor > min.insync.replicas 。为什么呢?设想⼀下加⼊两者相等的话,只要是有⼀个副本挂掉,整个分区就 ⽆法正常⼯作了。这明显违反⾼可⽤性!⼀般推荐设置成 replication.factor = min.insync.replicas + 1。
4,配置 unclean.leader.election.enable = false,当 leader 副本发⽣故障时就不会从 follower 副 本中和 leader 同步程度达不到要求的副本中选择出 leader ,这样降低了消息丢失的可能性。

浙公网安备 33010602011771号