概述
关于 kafka 的重要性这里就不再多说了,kafka 不仅解降低了大数据组件之间的耦合性,而且还能对接流实时计算框架,充当其流数据源,并支持接收大量数据输入,以类似于消息队列的方式组织统一管理。
官方定义:Apache Kafka® is a distributed streaming platform.即 kafka 是一个分布式流平台。通俗的说法是:Kafka是一种高吞吐量的分布式发布订阅消息系统。说白了即消息中间件,而消息中间件一般支持两种模式的队列:一是消息队列模式,二是发布订阅 (Pub-Sub) 模式。 Kafka 即是采用后者方式的轻量级消息系统、流平台。
这个系统需要满足如下三个特性:
- 能够对流记录(每条消息)进行发布、订阅。
- 能够支持容错地持久化每一条流记录。(注:采用时间复杂度O(1)的磁盘存储结构,即使TB级别以上的数据也可以常数时间访问)
- 能够及实地处理每一条实时的流记录消息。
为何使用?
- 解耦:分布式系统构件之间可以通过消息系统传递消息从而解除相互之间功能的耦合。
- 异步通信:在实现定义好Consumer消费者后,我们只需要在Producer生产者端将消息放入即可。无需立即对消息进行处理。
核心概念
你只要了解如下几个核心概念,基本就能从全局上把握 kafka 了,下面依次介绍:
- Broker
即代理服务器,kafka 部署在集群中的多台机器上,其中的每一台服务器即 Broker,它代表 kafka 的一个实例或节点,多个 Broker 构成一个 kafka 集群。 - Topic
即话题,生产或消费流记录(消息),都需要指定特定的 Topic,一般将同一业务数据、同一类型数据写入同一 Topic。
(注:一般生产环境上,消息的 Topic 代表其所属的类型,对应某个名字的消息队列,比如要记录网站用户行为,我们可以设计 PV,点击,登录等不同Topic) - Partition
即分区,因为一个 Topic 下可能会有大量的数据,一个 Broker 可能存不下,故一个 Topic 可以有多个分区,相当于把一个大流数据集分为多份,分别存在隶属于同一个 Topic 下的不同分区中。
(注:Topic 是逻辑概念,Partition 是物理概念,每个分区对应于一个物理文件夹,存储分区数据及索引文件) - Producer
即生产者,向 Broker 某一 Topic 主题发送数据的客户端。 - Consumer
即消费者,消费指定 Topic 下的数据。 - Consumer Group
即消费者组,每个 Consumer 隶属于某个特定的 Consumer Group,Producer 将一条消息发送给所有的 Consumer Group,但最终只能被 Consumer Group 下的唯一的一个 Consumer 消费。
(注:分组的目的是为了加快读取速度) - Replication
即副本,一个 Partition 分区可以有多个副本,存在不同的 Broker 中,提供容错保证。
部分详细架构分析
工作流程架构
下图完整地描述 kafka 的整体流程结构,如有不足欢迎补充。
如上图所示,有3个 Broker 代理服务器,有2个 Topic,其中 Topic1 有两个分区,Topic2 有1个分区,集群分区备份副本数为3。
这里需要注意的是:一个 Topic 可以被多个 Consumer Group 订阅,但是只能被其中的一个 Consumer 消费。这里 Consumer Group A 和 Consumer Group B 都订阅了 Topic 1 和 Topic 2。在Consumer Group 中所有 Consumer 是竞争关系,一个流记录(消息)只能被一个 Consumer 消费。上图中具体消费情况如下:
Consumer Group A 里面的 Consumer 1 消费着 Broker1 上面的 Topic1
Consumer Group A 里面的 Consumer 2 消费着 Broker3 上面的 Topic2
Consumer Group B 里面的 Consumer 3 消费着 Broker2 上面的 Topic1
Consumer Group B 里面的 Consumer 4 消费着 Broker3 上面的 Topic2
Consumer Group B 里面的 Consumer 5 没有消费任何 Topic
数据存储架构
- Topic 存储结构
一个 Topic 可以分为多个 Partition,以文件夹的形式落盘,而每个 Partition 则是一个先进先出(FIFO)的队列,在队尾追加消息,在队头读取。且在一个Topic 内部不能保证消息的顺序性,只能保证一个 Partition 内部的消息的有序序 ,如下图所示:
- Partition 存储结构
每个 Topic 的 Partition 在物理上以文件夹的形式存在,此文件夹中存在两种类型的文件,其一是以起始偏移量开头、以 .log 结尾的数据文件,用于存储流记录消息数据 ;其二是以 .index 或 .timeindex 结尾的索引文件,用以定位消息读取到的位置,提高消息写入和查询速度。它们统称为 Segment 文件。 - 偏移量
偏移量 OffSet 用于定位 Partition 分区中消息的顺序编号。哪个 Consumer 消费到那里,该 Consumer 的 Offset 就在哪里,不同 Consumer 可能有不同的 Offset 值,由 Zookeeper 维护偏移量 Offset。
(架构心得:传统消息系统将消费者消费到的 Offset 信息存储在代理服务器,而 kafka 简化设计,将 Offset 信息交由消费者各自保存,联同其他管理信息一并存在 Zookeeper 中,让代理服务器完全成为无状态的,这样便会极大地提高消息系统的容错性以及可扩展性。)
高可用
kafka 使用 ISR 副本管理机制来保证其高可用性。首先需要明确 kafka 副本基本管理单位是 Partition 分区,如果我们指定了多个副本策略,则这些副本里只有一个为主副本(Leader),其他为次级副本 (Follower),所有读写均和主副本来响应。
ISR 具体运行机制是:将所有的次级副本(偶数)放到两个集合,其中一个集合被称为 ISR 集合,该集合里的数据始终与主节点数据保持一致,数据写入时,只有 ISR 集合中全部成功写入才算写入成功,在做主备切换时,直接且只允许从 ISR集合中选取将要转正的副本即可。
那么为何不采用 Zab(Zookeeper 采用的一致性协议)、或 Paxos 算法来保证 kafka 副本的数据一致性,而是采用另一套 ISR 副本管理机制来保证数据一致性呢?
原因其实很简单,因为在相同的副本容错条件下, ISR 机制可以维护更少的数据副本。比如 ISR 集合大小为 n+1(1主,n副,n为偶数),那么最多可以允许n个副本故障,而对于其他基于投票的一致性算法来说,则需要 2n + 1 个副本才能达到相同的容错性。
以上关于 kafka 原理及架构就讲这么多,大晚上的写完不容易,希望能对大家有所帮助,下篇文章会讲下 kafka 具体使用。