拓扑图
Topic
是一个逻辑概念,相当于给消息分配的标签
Partition
分区,topic 中的消息被分割为一个或多个的 partition,是一个物理概念
对应到系统上就是一个或若干个目录,一个分区就是一个日志文件
消息以追加的形式写入分区,先后以顺序的方式读取每个日志文件都是一个
log entry
序列。这个log entry
并非由一个文件构成,而是分成多个segment
Segment
段,将 Partition 进一步细分为若干个 segment,每个 segment 文件的大小相等
- 每个
segment
以该segment
第一条消息的offset
命名并以.kafka
为后缀- 另外会有一个索引文件,它标明了每个
segment
下包含的log entry
的offset范围
因为每条消息都被append
到该Partition
中,属于顺序写磁盘
,因此效率非常高
(顺序写磁盘效率比随机写内存还要高,这是Kafka高吞吐率的一个很重要的保证)
Broker
- Kafka 集群包含一个或多个服务器,每个 Kafka 中服务器被称为 broker。
- Broker 接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。
- Broker 为消费者提供服务,对读取分区的请求作出响应,返回已经提交到磁盘上的消息
-
Broker 是集群的组成部分,每个集群中都有一个 Broker 同时充当了
集群控制器 Leader
的角色(选举产生;每个 Broker 都可能成为 Leader,功能包括将分区 partition 分配给 broker 和监控 broker) -
集群中,一个分区从属于一个 Leader,但是一个分区可以分配给多个 Broker(非Leader),这时会发生
分区复制
(复制机制为分区提供了消息冗余,如果一个 broker 失效,那么其他活跃用户会重新选举一个 Leader 接管)
Producer
- 消息的发布者,会将某 topic 的消息发布到相应的 partition 中。
- 默认情况下把消息均衡地分布到主题的所有分区上,而并不关心特定消息会被写到哪个分区。
- 某些情况下,生产者会把消息直接写到指定的分区
Consumer
- 消费者,一个消费者可以消费多个 topic 的消息
- 对于某一个 topic 的消息,其只会消费同一个 partition 中的消息
Consumer Group
(本节所有描述都是基于Consumer high level API而非low level API)
同一Topic的一条消息只能被同一个Consumer Group内的一个Consumer消费;
但多个Consumer Group可同时消费这一消息
单播:所有的Consumer在同一个Group里
广播:只要每个Consumer有一个独立的Group就可以
Push vs. Pull
Producer
向Broker push
消息Consumer
从Broker pull
消息
push
:目标是以最快的速度传递消息,很难适应消费速率不同的Consumer
pull
:可以根据Consumer
的消费能力以适当的速度消费消息
Kafka delivery guarantee
At most once
At least once
Exactly once
消息队列
-
MQ 消息模型
-
消息队列分类
-
点对点
消息生产者生产消息发送到 Queue 中,然后消息消费者从 Queue 中取出并消费消息。
消息被消费后,Queue 中不再有存储,所以消费者不可能消费到已经被消费的消息。Queue 支持存在多个消费者,但是对于一条消息而言,只会有一个消费者可以消费
-
发布/订阅
消息生产者(发布)将消息发布到 Topic 中,同时有多个消费者(订阅)消费该消息。
与点对点方式不同,发布到 Topic 的消息会被所有订阅者消费
-
Kafka
-
Kafka 是分布式发布-订阅消息系统。在 Kafka 集群中,没有“中心主节点”的概念,集群中所有的服务器都是对等的,因此,可以在不做任何配置的情况下实现服务器的删除与添加,消息生产者和消费者也能够做到随意重启和机器的上下线
-
消息系统生产者和消费者部署关系
- 消息系统架构
-
术语
- 生产者:Producer,是消息产生的源头,负责生成消息并发送到Kafka
- 消费者:Consumer,是消息的使用方,负责消费Kafka服务器上的消息
Broker
:Kafka集群中的一台或多台服务器统称为Broker- 接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。
- 为消费者提供服务,对读取分区的请求作出响应,返回已经提交到磁盘上的消息
- 主题:Topic,由用户定义并配置在Kafka服务器,用于建立生产者和消息者之间的订阅关系:生产者发送消息到指定的Topic下,消费者从这个Topic下消费消息。
- 消息分区:Partition,一个Topic下会分为很多分区。例如:“kafka-test”这个Topic下可以分为6个分区,分别由两台服务器提供,那么通常可以配置让每台服务器提供3个分区,假如服务器ID分为为0,1,则所有的分区为0-0、0-1、0-2和1-0、1-1、1-2。
消息怎么备份的??
。Topic物理上的分区,一个topic可以分为多个partition,每个partition都是一个有序队列。partition中的每条消息都会被分配一个有序的id(offset)。 - Offset:消息存储在Kafka的Broker上,消费者拉取消息数据的过程中需要知道消息在文件中的偏移量,这个偏移量就是所谓的Offset
- 消费者分组:Group,用于归组同类消费者,在Kafka中,多个消费者可以共同消费一个Topic下的消息,每个消费者消费其中的部分消息,这些消费者就组成了一个分组,拥有同一个分组名称,通常也被称为消费者集群
-
Broker
- Message在Broker中通Log追加的方式进行持久化存储,并进行分区(partitions)
- 为了减少磁盘写入的次数*,broker会将消息暂时buffer起来,当消息的个数(或尺寸)达到一定阀值时,再flush到磁盘,这样减少了磁盘IO*调用的次数
- Broker没有副本机制,一旦broker宕机,该broker的消息将都不可用。
Message消息是有多份的 --- 怎么实现的??
- Broker不保存订阅者的状态,由订阅者自己保存
- 无状态导致消息的删除成为难题(可能删除的消息正在被订阅),Kafka采用基于时间的SLA(服务水平保证),消息保存一定时间(通常为7天)后会被删除
- 消息订阅者可以rewind back到任意位置重新进行消费,当订阅者故障时,可以选择最小的*offset(id)*进行重新读取消费消息
-
Kafka的Message组成
- Message消息:是通信的基本单位,每个 producer 可以向一个 topic(主题)发布一些消息
- Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的。每个topic又可以分成几个不同的partition(每个topic有几个partition是在创建topic时指定的*),每个partition存储一部分Message*
这里每个partition存储的消息是不一样的
- partition中的每条Message包含了以下三个属性:
- offset:消息唯一标识*:*对应类型:long
- MessageSize:对应类型:int32
- data:message的具体内容
-
Kafka 的 Partitions 分区
这些partition是将一条消息进行切分 OR 仅仅是分散到不同server上?怎么实现消息备份的??
- Kafka基于文件存储。通过分区,可以将日志内容分散到多个server上*,来避免文件尺寸达到单机磁盘的上限,每个partiton都会被当前server(kafka实例)*保存
- 可以将一个topic切分多任意多个partitions,来消息保存*/*消费的效率
- 越多的partitions意味着可以容纳更多的consumer,有效提升并发消费的能力
-
Kafka的Consumers**
消息和数据消费者,订阅 topics并处理其发布的消息的过程叫做 consumers
- 在kafka中,我们可以认为一个group是一个“订阅者”,一个Topic中的每个partition只会被一个“订阅者”(Group)中的一个consumer消费,不过一个consumer可以消费多个partitions中的消息(消费者数量小于Partitions的数量时)
(注意:kafka的设计原理决定,对于一个topic,同一个group中不能有多于partitions个数的consumer同时消费,否则将意味着某些consumer将无法得到消息) - 一个partition中的消息只会被group中的一个consumer消费。每个group中consumer消息消费互相独立
- 在kafka中,我们可以认为一个group是一个“订阅者”,一个Topic中的每个partition只会被一个“订阅者”(Group)中的一个consumer消费,不过一个consumer可以消费多个partitions中的消息(消费者数量小于Partitions的数量时)
-
Kafka持久化
- partition是一个物理概念,对应到系统上就是一个或若干个目录
- 消息以追加的形式写入分区尾部,然后以顺序的方式读取
- 一个主题包含无数个partition,因此无法保证在整个 topic 中的有序(单 partition 可以保证有序)
Kafka
通过分区来实现数据冗余和伸缩性- 分区可以分布在不同的服务器上(一个主题可以跨越多个服务器)
Segment
译为段,将 partition 进一步细分为若干个 segment,每个 segment 的大小相等
-
一个Topic可以认为是一类消息,每个topic将被分成多个partition(分区),每个partition在存储层面是append log文件。任何发布到此partition的消息都会被直接追加到log文件尾部,每条消息在文件中的位置称为offset(偏移量),partition以文件形式存储在文件系统中
-
log文件根据broker中的配置需求,保留一定时间后删除来释放磁盘空间
-
数据文件建立索引:稀疏存储,每隔一定字节的数据建立一条索引
-
Kafka的分布式实现
-
Kafka的通讯协议
- Kafka的Producer、Broker和Consumer之间采用的是一套自行设计基于TCP层的协议
- 基本数据类型:(Kafka是基于Scala语言实现的,类型也是Scala中的数据类型)
- Kafka通讯的基本单位是Request/Response
- 通讯过程
- 客户端打开与服务器端的Socket
- 往Socket写入一个int32的数字(数字表示这次发送的Request有多少字节)
- 服务器端先读出一个int32的整数从而获取这次Request的大小
- 然后读取对应字节数的数据从而得到Request的具体内容
- 服务器端处理了请求后,也用同样的方式来发送响应
-
Kafka采用是经典的Reactor(同步IO)模式,也就是1个Acceptor响应客户端的连接请求,N个Processor来读取数据,这种模式可以构建出高性能的服务器
-
数据传输的事务定义
- at most once:发送一次,无论成败,将不会重发
- at least once:至少发送一次,如果消息未能接受成功,可能会重发,直到接收成功
- exactly once:消息只会发送一次
参考地址: