以下是本消息队列系列文章的传送门:
在通过消息队列(一)与消息队列(二),相信大家已经对消息队列的几大应用场景,以及各大消息队列中间件的优缺点,那么我们接下来将要讲述的是分布式发布订阅消息系统——kafka的一些相关概念与术语的介绍。
1、简介
1.1 概述
Kafka是最初由Linkedin公司开发,是一种高吞吐量的分布式发布订阅消息系统,常见可以用于web/nginx日志、访问日志,消息服务等,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。
Kafka主要设计目标如下:
- 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能;
- 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条消息的传输;
- 支持Kafka Server间的消息分区,及分布式消费,同时保证每个partition内的消息顺序传输;
- 同时支持离线数据处理和实时数据处理;
- Scale out:支持在线水平扩展。
1.2 消息传递模式
常见的消息传递模式有两种、分别是:
-
点对点传递模式
:在点对点消息系统中,消息持久化到一个队列中。此时,可以有一个后多个消费者消费队列中的数据,但是一条消息只能被消费一次。当一个消费者消费了队列中的某条数据之后,该条数据则从消息队列中删除。该模式下,既有多个消费者同时消费数据,也能保证数据处理的顺序。如下图所示。
-
发布-订阅消息传递模式
:在发布-订阅消息系统中,消息将被持久化到一个topic中,与点对点消息系统的区别是,消费者可以订阅一个或多个topic,消费者可以消费该topic中所有的数据,同一条数据可以被多个消费者消费,且数据消费后不会立马删除,且发布者发送到topic中的消息,只有订阅了topic的订阅者才会收到。在发布-订阅消息系统中,消息的生产者成为发布者,消费者称为订阅者。如下图所示。
2、kafka中常用的术语
我们通过下图的kafka简单示例架构来熟悉kafka中的术语。
Kafka架构示例我们先解释图中出现的术语,最后再对整个图的内容做一个详细解释。
2.1 Topic
每天发布到Kafka集群的消息都有一个主题类别,这个主题类别称为Topic
。物理上不同的Topic的消息可能存储在同一broker中,也有可能不在同一broker中,但逻辑上只要用户指定消息的topic即可消费关于该topic
的有关数据,而不必关心数据的物理存储。
2.2 Partition
Topic中的数据分割为一个或多个分区(partition
)。partition有以下特性:
- 每个Topic至少有一个partition;
- 每个partition中的数据使用多个segment文件存储;
- partition中的数据是有序的,而不同partition间的数据丢失了数据的顺序(即我们无法知道哪个partition的数据是最先的或最后的);
- 如果topic有多个partition,消费数据时就不能保证数据的顺序。因此,在需要严格保证消息的消费顺序的场景下,需要将partition的数目设置为1。
2.3 Broker
在上图中我们可以在Kafka Cluster
(即kafka集群)中看到,集群里包含了一个或多个服务器,这些服务器节点称为Broker
。Broker存储着topic的数据,常见的存储数据方式如下:
- 如果某topic有N个partition,集群有N个Broker,那么每个Broker存储该topic的一个partition;
- 如果某topic有N个partition,集群有N+M个Broker,那么其中有N个broker存储该topic的一个partition,剩下的M个Broker不存储该topic的partition数据;
- 如果某topic有N个partition,集群的Broker数目少于N个,那么一个Broker存储该topic的一个或多个partition。(
注意
:在实际生产环境中,一般会尽量避免这种情况发生,因为这种情况容易导致Kafka集群数据不均衡)。
2.4 Producer
Producer
即数据的发布者,该角色将消息发布到Kafka的topic中。Broker接收到生产者发送的消息后,将该消息追加
到当前用于追加数据的segment文件中。生产者发送的消息,可以存储到每一个partition中,也可以指定数据存储的partition。
2.5 Consumer
Consumer
即为消费数据的一方,消费者可以从Broker中读取数据。消费者可以消费多个topic中的数据。
2.6 Offset
Offset
即偏移量(位置),标识分区每条记录的位置,是分区当中每条记录的唯一标识。消费者通过记录当前消费到的偏移量来记录消费情况。
2.6 Consumer Group
Consumer Group
即为消费者组,用于占用式消费。我们可以为每个Consumer指定Group name,若不指定Group name则属于默认的Group。消费者组有以下特性:
- 对于同一个topic的同一个partition,消费者消费时,会按消费者组来记录消费偏移,即一个组内只维护一个消费偏移。假设消费者1和消费者2同属一组,消费者1消费了一部分数据,那么消费者2此时再来消费数据的话,是无法消费到消费者1消费了的那部分数据的。如下图:
- 不同的group之间记录不同的offset,这样在不同程序读取同一个topic时,才不会因为offset互相影响。
2.7 Leader
每个partition有多个副本,其中有且仅有
一个作为Leader
,Leader是当前负责数据读写的partition。
2.8 Follower
Follower
跟随Leader,即与Leader数据保持一致。其特性如下:
- 所有写请求都通过Leader来路由,即Leader数据的变更会广播给所有Follwer;
- Follwer与Leader保持数据同步;
- 如果Leader失效,则从Follower中选举出一个新的Leader;
- 当Follower挂掉、卡住或同步太慢,Leader会把这个Follower从"in sync replicas"(ISR)列表中删除,重新创建一个Follower。
2.8 架构示例图详细解释
Kafka架构示例
- 我们可以看到,图中主要分为四个部分。分别是
Producer
、Kafka Cluster
、Consumer Group
和Zookeeper注册中心
; - Producer中有两个生产者A和B。Kafka Cluster中有3个Broker(即3台服务器)。Consumer Group中有3个消费者,其中1和2消费者属于同一个消费者组,消费者3属于默认消费者组。Zookeeper主要负责统一管理Kafka Cluster中的所有注册的Broker、消费者组中的消费者;
- 某个主题消息(Topic A)设置了两个分区,分别是
partition 0
与partition 1
,每个partition都有其备份分区。其中存储在Broker 1中的partition 0为partition 0的Leader(生产者生产消息与消费者消费消息时主要是与Leader交互),partition 0的备份存储在Broker 2中(图中绿色部分)。存储在Broker 2中的partition 1为partition 1的Leader,partition 1的备份存储在Broker 1中(图中浅蓝色部分); - 首先,最左边的是两个生产者A、B。生产者A生产了
message-A
这个消息,将消息分别发送至两个partition的Leader中。生产者B将生产的消息发送到只有一个分区的Topic B的partition 0分区中。 - 然后在消费阶段,Consumer 1消费Topic A的partition 0中的消息。Consumer 2由于和Consumer 1属于一个消费者组(对相同partition属于占用式消费,但消费不同partition时可以同时进行消费),所以此时Consumer 2可以消费Topic A的partition 1中的消息。Consumer 3 消费Topic B中的partition 0中的消息。
网友评论