Kafka总结

Kafka

Kafka 是什么

1
2
3
4
5
6
7
8
Kafka 是一个分布式流式处理平台。
流平台具有三个关键功能:

消息队列:发布和订阅消息流,这个功能类似于消息队列,这也是 Kafka 也被归类为消息队列的原因。

容错的持久方式存储记录消息流:Kafka 会把消息持久化到磁盘,有效避免了消息丢失的风险。

流式处理平台:在消息发布的时候进行处理,Kafka 提供了一个完整的流式处理类库。

应用场景

1
2
3
4
Kafka 主要有两大应用场景:

消息队列:建立实时流数据管道,以可靠地在系统或应用程序之间获取数据。
数据处理:构建实时的流数据处理程序来转换或处理数据流。

和其他消息队列相比,Kafka的优势

1
2
3
4
5
6
7
8
9
经常提到 Kafka 的时候就已经默认它是一个非常优秀的消息队列了,也会经常拿它与 RocketMQ、RabbitMQ 对比。 

Kafka 相比其他消息队列主要的优势如下:

极致的性能:基于 Scala Java 语言开发,设计中大量使用了批量处理和异步的思想,最高可以每秒处理千万级别的消息。

生态系统兼容性无可匹敌:Kafka 与周边生态系统的兼容性是最好的没有之一,尤其在大数据和流计算领域。

在早期的时候 Kafka 并不是一个合格的消息队列,早期的 Kafka 功能不完备并且有一些小问题,比如丢失消息、不保证消息可靠性等等。这也和 LinkedIn 最早开发 Kafka 用于处理海量的日志有很大关系,后面误打误撞在消息队列领域占据了一席之地。随着后续的发展,这些短板都被 Kafka 逐步修复完善。所以,Kafka 作为消息队列不可靠这个说法已经过时!

队列模型:早期的消息模型

1
2
3
4
5
6
使用队列(Queue)作为消息通信载体,满足生产者与消费者模式,一条消息只能被一个消费者使用,未被消费的消息在队列中保留直到被消费或超时。
比如:我们生产者发送 100 条消息的话,两个消费者来消费一般情况下两个消费者会按照消息发送的顺序各自消费一半(你一个我一个)。

队列模型存在的问题:

存在这样一种情况:我们需要将生产者产生的消息分发给多个消费者,并且每个消费者都能接收到完成的消息内容。这种情况,队列模型就不好解决了。杠精说:可以为每个消费者创建一个单独的队列,让生产者发送多份。这是一种非常愚蠢的做法,浪费资源不说,还违背了使用消息队列的目的。

发布-订阅模型:Kafka 消息模型

1
2
3
4
5
6
发布-订阅模型主要是为了解决队列模型存在的问题。

发布订阅模型(Pub-Sub)使用主题(Topic) 作为消息通信载体,类似于广播模式;
发布者发布一条消息,该消息通过主题传递给所有的订阅者,在一条消息广播之后才订阅的用户则是收不到该条消息的。

发布-订阅模型中,如果只有一个订阅者,那它和队列模型就是一样的。所以说,发布-订阅模型在功能层面上是可以兼容队列模型的。

Producer、Consumer、Broker、Topic、Partition

1
2
3
4
5
6
7
8
9
10
11
Kafka 重要的概念:

Producer(生产者): 产生消息的一方。
Consumer(消费者): 消费消息的一方。
Broker(代理服务器): 一个独立的 Kafka 实例,多个 Kafka Broker 组成一个 Kafka Cluster。
---
每个 Broker 中又包含了 Topic 以及 Partition:

Topic(主题): Producer 将消息发送到特定的主题,Consumer 通过订阅特定的 Topic 来消费消息。

Partition(分区): Partition 属于 Topic 的一部分。一个 Topic 可以有多个 Partition,并且同一 Topic 下的 Partition 可以分布在不同的 Broker 上,这也就表明一个 Topic 可以横跨多个 Broker。

Kafka 的多副本机制

1
2
3
4
5
Kafka 为分区(Partition)引入了多副本(Replica)机制。

分区(Partition)中的多个副本之间会有一个 leader 副本,其他副本称为 follower。我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。

生产者和消费者只与 leader 副本交互。可以理解为其他副本只是 leader 副本的拷贝,它们的存在只是为了保证消息存储的安全性。当 leader 副本发生故障时会从 follower 中选举出一个 leader,但是 follower 中如果有和 leader 同步程度达不到要求的参加不了 leader 的竞选。

Kafka 多分区,多副本的好处

1
2
3
Kafka 给特定 Topic 指定多个 Partition, 而各个 Partition 可以分布在不同的 Broker 上, 这样能提供比较好的并发能力(负载均衡)。

Partition 可以指定对应的 Replica 数,这也极大地提高了消息存储的安全性,提高了容错能力,不过也相应的增加了所需要的存储空间。

Kafka 如何保证消息的消费顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
在使用消息队列的过程中经常有业务场景需要严格保证消息的消费顺序,比如我们同时发了 2 个消息,这 2 个消息对应的操作分别对应的数据库操作是:更改用户会员等级、根据会员等级计算订单价格。假如这两条消息的消费顺序不一样造成的最终结果就会截然不同。

KafkaPartition(分区)是真正保存消息的地方,我们发送的消息都被放在这里。而Partition(分区) 又存在于 Topic(主题) 这个概念中,并且我们可以给特定 Topic 指定多个 Partition

每次添加消息到 Partition(分区) 的时候都会采用尾加法。Kafka 只能为我们保证 Partition(分区) 中的消息有序,而不能保证 Topic(主题)Partition(分区) 的有序。

所以,有一种很简单的保证消息消费顺序的方法:1Topic 只对应 1Partition。这样当然可以解决问题,但是破坏了 Kafka 的设计初衷。

Kafka 中发送 1 条消息的时候,可以指定 topic, partition, key, data(数据)4 个参数。如果你发送消息的时候指定了 Partition 的话,所有消息都会被发送到指定的Partition。并且,同一个 key 的消息可以保证只发送到同一个 partition,可以采用表/对象的 id 来作为 key

总结,保证 Kafka 中消息消费的顺序,有了两种方法:
11Topic 只对应一个 Partition
2)发送消息的时候指定 key/Partition (推荐)

参考资料

https://snailclimb.gitee.io/javaguide/


Kafka总结
https://lcf163.github.io/2020/07/07/Kafka总结/
作者
乘风的小站
发布于
2020年7月7日
许可协议