时过境迁,Kafka 已经把自己的定位改为日志提交服务。现在官方的说法是:
Kafka是一个分布式的、分片的、多副本的日志提交服务。基于一个统一的设计,它同样也提供消息系统的功能。
(之前的说法是:
Kafka 本质上是一个分布式的消息队列,但是也可以用来做日志传输的中转组件。它的主要特点如下:
-
分布式。内部包含多个Broker,在客户端使用分片机制来实现负载均衡。
-
高吞吐。较其他消息队列,Kafka 精简掉很多高级特性,但这样也使得它更容易实现高吞吐。
-
可靠性。所有的数据会被持久化在内部 Broker 的磁盘中,支持多副本,并且可以为不同重要性的群组配置不同的副本数量。
- 数据订阅。和所有常见的消息队列一样支持数据的订阅,因此很容易在后面接入流式计算的系统。)
术语介绍
topic:Kafka 按消息类别来管理日志,每个类别称为一个 topic
producer:我们称发布消息到 Kafka 系统的进程为 producer
consumer:我们称从 Kafka 订阅并处理消息的进程为 consumer
broker:Kafka 部署在一个集群上,集群的每个节点称为一个 broker
下图是 Kafka 的一个顶层架构图,producers 通过网络发送消息到 Kafka 集群,集群再把这些消息转发给 comsumers。
Topics and Logs
先来看看 topic,topic 是一个类别或者是消息源的名字,Kafka 集群对每个 topic 都做了下图这样的划分(partition)。
每一个划分是一个持续增加的有序的不变的消息队列,消息队列中的每条消息都被打上了一个序号,叫偏移(offset),用来在划分中区分不同消息。
日志服务器的划分有两个目的,一个是方便水平扩展,另一个是为数据的并行处理打了很好的基础。
Kafka 集群保留配置时间内的全部消息数据,Kafka 的性能跟它保存的数据是常量关系;它的 consumer 仅保留了访问的偏移信息,通常的 consumer 处理偏移的方式是随着消息的读取线性增加,但你也可以把偏移调到较早以前来重新处理一些消息。上述的特性使得 Kafka 的 consumer 变得非常便宜,你可以很快地增加一个 consumer 而对系统几乎完全没有影响。
Distribution
在 Kafka 中可以为一个数据划分配置多个副本来做容错,不同的副本存储在集群的不同节点上。Kafka 的副本采用 leader-followers 机制,具体就是对某一个数据划分,同时只有一个 leader,负责该划分中所有数据的读写,其他的 follower 只对数据做副本同步;当 leader 失效的时候再从 follower 中选出一个节点充当 leader。
每个 Kafka 集群节点充当一些数据划分的 leader 和其他一些数据划分的 follower,以此来达到负载均衡。
Producer & Consumer
Producer 发布消息到 Kafka 系统的时候可以选择发送到哪个数据划分中,一般可以选择随机发送的方式来做负载均衡,也可以根据一定的语义来切分数据。
传统的消息系统不外乎两种模式:队列和订阅。队列模式一般是一个消费者池逐个的从服务中把消息分掉;订阅模式中一个消息会被广播到所有的消费者。Kafka 通过消费群组(consumer group)的概念把两种模式统一起来。
Consumer 把自己标记成在某个消费群组里,所有的消息都会广播到订阅的消费群组中,同一个消费群组中的消息被群组中的消费者实例并发处理。
传统的消息队列在服务其上统一按序保存,由于多线程的原因,当开多个 consumer 的时候同一个消费者受到的消息可能是乱序的。一些系统为了解决这个问题就采用互斥消费者(exclusive consumer)模式去绕,但这样的问题就导致系统不能并发。
Kakfa 面对这样的问题会好一些,它可以把数据划分跟消费群组中的消费者一一对应,这样既保证同一个消费者消费的信息是有序的,同时也能解决系统负载的问题。
Guarantees
Kafka 提供如下系统级的保证:
- 同一个 producer 向特定 topic 的划分发送的消息将按照它们被发送的顺序存放。
- 一个 consumer 实例将按照存放的顺序看到消息。
- 对于配置了 N 个副本的 topic,最高在 N-1 个服务器挂掉的前提下还能保证日志数据不丢失。
通过上述说明,我们了解了 Kafka 的基本设计思想。先休息一下,然后我们看看它能用在哪些场景。