基本概念
Apache Kafka是一个基于publish-subscribe模型的高吞吐、低延迟、高容错的分布式流平台。
kafka中常见概念:
-
broker
部署kafka实例的服务器节点 -
topic
消息组织的单元,publish/subscribe的对象 -
partition
每个topic由1个或者多个partition组成。分区在物理层面,不同分区对应着不同的数据文件。record按照顺序追加写到分区内。分区提高了kafka的可扩展性和并发吞吐性能。 -
record
实际写入到kafka中的消息记录,每个record包含一个key、value和timesatmp -
producer
生产者,向Kafka中发送record -
consumer
消费者,从kafka中消费record -
consumer group
消费组,一个消费可以订阅多个topic,一个topic中的partition只能被一个消费组内的一个消费者消费,但是可以可以同时被不同的消费组消费
基本原理
Topics和Logs
一个topic是一个类别,是消息记录发布和订阅的对象。
topic内部的消息记录按照partition(分区)组织存储,publish到该topic的消息记录会均匀的写入到各个partition,如下图所示(官网复制)
partition内部,消息记录以有序的、不可更改的次序追加写方式进行组织,每个消息记录被分配一个序列ID来唯一标示,该序列ID称之为offset。
用户可以对topic内部的消息记录设置过期时间,在有效期内,kakka集群会持久化的存储发布到到该集群的消息记录,不管该消息记录是否被消费过。过期的消息记录会被kafaka删除,以释放空间。kafka的存储方式决定了其性能不会随着数据量的增加而下降,所以无需担心存储长时间的数据,我们要考虑的是kafka集群的存储空间是否充足。
对每个consumer,唯一需要维护的元数据是其消费的offset,该offset由consumer自己维护。通常情况下,在consumer消费消息记录时,consumer会线性增加其offset;不过consumer也可以根据需求任意修改其offset。这些特性使得consumer的增加和删除对集群和其他consumer影响非常小。
对于topic内部partition的分区设计,其目的主要有两个:线性扩展topic的存储空间(不受限于单个server存储的限制);提高并发,以提升性能。
Distribution
topic的partitions分布在kafka集群的servers上,每个server处理一个partition的数据和请求。每个partition可以配置副本数来冗灾,每个partition会有一个server作为leader角色,0个或者多个servers作为followers。leader server处理该partiton的读写请求,followers被动的从leader server复制数据做备份。如果leader server挂掉,followers中的一个自动升级为leader server。同时每个即要是一些partition的leader,又要是其他一些其他paritition的followers,以此来平衡集群。
Producers
Producers发布数据到它们选定的topic。producer负责消息记录具体发布到哪个partition,算法可以是简单的round-robin来做负载均衡,也可以基于消息记录中相关key来做路由。
Consumers
consumers用consumer group进行组织,kafka topic订阅的对象是consumer group,topic中每条消息记录会被传递到每个订阅的consumer group中的一个consumer实例。
如果所有的consumer实例都属于一个consumer group,那么所有的消息记录都会被均衡的传递给响应的consumer实例。
一个2个server的kafka集群,包含4个parititons(P0-P3),有两个消费组对其进行了订阅。消费组A有2个consumer实例,消费组B有4个consumer实例。如下图
实际的实现中,topic的每个parition会唯一被每个订阅的消费组中的一个consumer实例消费,如果有新的consumer加入消费组,新加入的consumer实例会从该消费组的其他consumer实例接管一些partitions;如果一个consumer挂掉了,其消费的partitions会被剩余的consumer实例获取。
kafka只提供partition内部的保序,不同的partition之间并没有顺序可言。对大部分应用程序而言,partition内部的保序和按照key进行数据分区已经可以满足其顺序需求。如果需要全局保序,那么一个topic只能包含一个partition,同时也意味这,一个消费组只能有一个consumer实例去消费topic数据。
Guarantees
kafka提供了如下保证:
- 被发送到同一个partition的消息会按照其发送的顺序进行追加写入到parititon。即,如果M1和M2被同一个producer发送,M1先被发送,那么M1的offset将会比M2的小,且先被写入。
- consumer实例看到的消息顺序是消息存储的顺序
- N副本的topic,允许N-1台server故障,而不丢失任何提交的日志。