Kafka与Pulsar概述、对比
本章简单介绍Kafka与Pulsar的起源发展、系统特性，以及部分基础概念，为本书后面的内容做铺垫。
1.1简介
Apache Kafka（简称Kafka）是由LinkedIn公司开发的分布式消息流平台，于2011年开源。Kafka是使用Scala和Java编写的，当下已成为最流行的分布式消息流平台之一。Kafka基于发布/订阅模式，具有高吞吐、可持久化、可水平扩展、支持流数据处理等特性。
Apache Pulsar（简称Pulsar）是雅虎开发的“下一代云原生分布式消息流平台”，于2016年开源，目前也在快速发展中。Pulsar集消息、存储、轻量化函数式计算为一体，采用计算与存储分离架构设计，支持多租户、持久化存储、多机房跨区域数据复制，具有强一致性、高吞吐、低延时及高可扩展性等流数据存储特性。
1.2特性
Kafka与Pulsar都是优秀的分布式消息流平台，它们都提供了以下基础功能：
（1）消息系统：Kafka与Pulsar都可以实现基于发布/订阅模式的消息系统，消息系统可以实现由消息驱动的应用程序—生产者负责产生并发送消息到消息系统，消息系统将消息投递给消费者，消费者收到消息后，执行自己的逻辑。
这种消息驱动机制具有以下优点：
- 系统解耦：生产者与消费者逻辑解耦，互不干预。如果需要对消息添加新的处理逻辑，则只需要添加新的消费者即可，非常方便。
- 流量削峰：消息系统作为消息缓冲区，以低成本将上游服务（生产者）的流量洪峰缓存起来，下游服务（消费者）按照自身处理能力从消息队列中读取数据并进行处理，避免下游服务由于大量的请求流量而崩溃。
- 数据冗余：消息系统将数据缓存起来，直到数据被处理，避免下游服务由于崩溃下线、网络阻塞等原因无法及时处理数据而导致数据丢失。
（2）存储系统：Kafka与Pulsar可以存储大量数据，并且客户端控制自己读取数据的位置，所以它们也可以作为存储系统，存储大量历史数据。
（3）实时流数据管道：Kafka与Pulsar可以构建实时流数据管道，流数据管道从MySQL、MongoDB等数据源加载数据到Kafka与Pulsar中，其他系统或应用就可以稳定地从Kafka与Pulsar中获取数据，而不需要再与MySQL等数据源对接。为此，Kafka提供了Kafka Connect模块，Pulsar提供了Pulsar IO模块，它们都可以构建实时流数据管道。
（4）流计算应用：流计算应用不断地从Kafka与Pulsar中获取流数据，并对数据进行处理，最后将处理结果输出到Kafka与Pulsar中（或其他系统）。流计算应用通常需要根据业务需求对流数据进行复杂的数据变换，如流数据聚合或者join等。为此，Kafka提供了Kafka Streams模块，Pulsar提供了Pulsar Functions模块，它们都可以实现流计算应用。另外，Kafka与Pulsar也可以与流行的Spark、Flink等分布式计算引擎结合，构建实时流应用，实时处理大规模数据。
Kafka与Pulsar都具有（或追求）以下特性：
（1）高吞吐、低延迟：它们都具有高吞吐量处理大规模数据的能力，并且能够低延迟处理消息。这也是大多数消息流平台追求的目标。
（2）持久化、一致性：Kafka与Pulsar都支持将消息持久化存储，并提供数据备份（副本）功能，保证数据安全及数据一致性，它们都是优秀的分布式存储系统。
（3）高可扩展性（伸缩性）：Kafka与Pulsar都是分布式系统，会将数据分片存储在一组机器组成的集群中，并支持对集群进行扩容，从而支持大规模的数据。
（4）故障转移（容错）：Kafka与Pulsar支持故障转移，即集群中某个节点因故障下线后，并不会影响集群的正常运行，这也是优秀的分布式系统的必备功能。
Kafka与Pulsar虽然提供的基础功能类似，但它们的设计、架构、实现并不相同，本书将深入分析Kafka与Pulsar如何实现一个分布式、高扩展、高吞吐、低延迟的消息流平台。另外，本书也会介绍Kafka与Pulsar中连接器、流计算引擎等功能的应用实践。
下面介绍Kafka与Pulsar中涉及的基础概念，这些概念会在本书后面反复使用。
将Kafka与Pulsar都视为一个简单的消息系统，消息流转流程如图1-1所示。
图1-1中展示了消息系统中的4个基本概念。它们在Kafka与Pulsar中都存在，并且含义相同。
- 消息Message：Kafka与Pulsar中的数据实体。
- 生产者Producer：发布消息的应用。
- 消费者Consumer：订阅消息的应用。
- 主题Topic：Kafka与Pulsar将某一类消息划分到一个主题，主题是消息的逻辑分组，不同主题的消息互不干预。
下面结合一个例子说明上述概念。假如存在一个用户服务，该用户服务创建了一个主题“userTopic”，每当有新用户注册时，用户服务都会将一个消息发送到该主题中，消息内容为“新用户注册”。当前有两个服务订阅了该主题的消息：权益服务和权限服务。权益服务收到消息后，负责给新用户创建权益。权限服务收到消息后，负责给新用户分配权限。该例子中的消息即用户服务发送的数据实体，生产者是用户服务。消费者是权益服务与权限服务。
1.3.1Kafka基础概念
下面介绍Kafka的一些基础概念。
- Kafka消费组：Kafka将多个消费者划分到一个逻辑分组中，该分组即一个消费组。这个概念比较重要，结合上面的例子进行说明，在Kafka中，权益服务所有的消费者都可以加入一个权益消费组rightsGroup，而权限服务所有的消费者都可以加入一个权限消费组guthorityGroup。不同消费者之间消费消息互不干预。
- Broker：Kafka服务节点，可以将Broker理解为一个Kafka的服务节点或者服务进程（下面将其统称为Broker节点），多个Broker节点可以组成一个Broker集群。
- 分区Partition：Kafka定义了分区的概念，一个主题由一个或多个分区组成，Kafka将一个主题的消息划分到不同的分区，并将不同分区存储到不同的Broker，从而实现分布式存储（典型的数据分片思想），每个分区都有对应的下标，下标从0开始。
- 副本Replica：Kafka中每个分区都有一个或多个副本，其中有1个leader副本，0个或多个follow副本，每个副本都保存了该分区全部的内容。Kafka会将一个分区的不同副本保存到不同的Broker节点中，以保证数据的安全。本书后面会详细分析Kafka副本同步机制。
- AR（Assigned Replicas）：分区的副本列表，即一个分区所有副本所在Broker的列表。
- ISR：分区中所有与leader副本保持一定程度同步（即不能落后太多）的副本会组成ISR（In-Sync Replicas）集合。ISR集合中包括leader副本，可以将其理解为已同步副本（不一定完全同步，但不会落后太多）。
- ACK机制：ACK（消息确认）机制是消息系统中保证数据不丢失的的重要机制，消息系统ACK机制与HTTP的ACK机制非常类似。消息系统ACK机制可以分为两部分：
- Broker收到生产者发送的消息并成功存储这些消息后，返回成功响应（可以将该成功响应理解为一种ACK）给生产者，这时生产者可以认为消息已经发送成功，否则生产者可能需要做一些补偿操作，如重发消息。
- 消费者收到Broker投递的消息并成功处理后，返回消费成功的ACK信息给Broker，Broker收到这些ACK信息后，可以认为消费者已经成功消费了消息，否则Broker可能需要做一些补偿操作，如重新投递消息。该场景下消费者通常需要将消费成功的消息位置（或者消息Id等）发送给Broker，并且Broker需要存储这些消费成功的位置，以便后续消费者重启后从该位置继续消费。该场景也是我们关注的重点。
在Kafka中，每个消息都存在一个偏移量offset，如果将一个Kafka主题理解为一个简单的消息数组，那么可以将消息偏移量理解为该消息在该数组中的索引。消费者会将最新消费成功的消息的下一个偏移量发送给Broker（代表该偏移量前面的消息都已经消费成功），Broker会存储这些偏移量，以记录消费者的最新消费位置。为了方便描述，本书后面将消费者提交ACK信息中的偏移量称为ACK偏移量。
另外，Kafka与Pulsar都使用ZooKeeper存储元数据，完成分布式协作等操作，ZooKeeper是一个分布式协作服务，专注于协作多个分布式进程之间的活动，可以帮助开发人员专注于应用程序的核心逻辑，而不必担心应用程序的分布式特性。本书后面会详细分析ZooKeeper为Kafka与Pulsar提供了哪些服务。Kafka 2.8开始提供KRaft模块，支持Kafka脱离ZooKeeper独立部署运行，本书后面也会详细分析该模块的设计与实现。
图1-2展示了Kafka集群的基础架构。
1.3.2Pulsar基础概念
Pulsar中有以下基础概念：
- Pulsar订阅组：Pulsar可以将多个消费者绑定到一个订阅组中，类似于Kafka的消费组。同样使用前面“用户服务”的例子进行说明，在Pulsar中，权益服务所有的消费者都可以绑定一个权益订阅组rightsSubscription，而权限服务所有的消费者都可以绑定一个权限订阅组guthoritySubscription，不同订阅组之间消费消息互不干预。
- 非分区主题、分区主题：Kafka中每个分区都与一个Broker绑定，而Pulsar中每个主题都与一个Broker绑定，主题的消息固定发送给绑定的Broker节点。而Pulsar中也有“分区主题”的概念，分区主题由一组非分区的内部主题组成（下面将Pulsar中组成分区主题的非分区内部主题简称为内部主题），每一个内部主题都与一个Broker绑定，这样一个分区主题可以将消息发送到多个Broker，避免Pulsar单个主题的性能受限于单个Broker节点。
- Broker：Pulsar集群中的服务节点。需要注意，Pulsar由于采用计算、存储分离的架构，因此Pulsar Broker节点只负责计算，并不负责存储，Pulsar Broker节点会完成数据检验、负载均衡等工作，并将消息转发给Bookie节点。
- Bookie：Pulsar利用BookKeeper服务实现存储功能，BookKeeper中的节点被称为Bookie节点。BookKeeper框架是一个分布式日志存储服务框架，本书后面会详细分析它。Pulsar中的Bookie节点负责完成消息存储工作。
- Ledger：BookKeeper的数据集合，生产者会将数据写入Ledger，而消费者从Ledger中读取数据。为了数据安全，BookKeeper会将一个Ledger的数据存储到多个Bookie节点中，实现数据备份。
- Entry：Ledger中的数据单元，Ledger中的每个数据都是一个Entry。可以将Ledger理解为一个账本，Entry则是账本中的一个条目。
- 租户、命名空间：Pulsar定义了租户、命名空间的概念，Pulsar是一个多租户系统，它给不同的租户分配不同的资源，并保证不同租户之间的数据相互隔离，互不干预，这样可以支持多团队、多用户同时使用一个Pulsar服务。每个租户还可以创建多个命名空间，命名空间为主题的逻辑分组。可以将Pulsar理解为一个大房子，每个租户是房子里的一个房间，并且这个房间的空间划分为不同的区域（命名空间），不同区域存放不同的物件。例如，用户服务可以创建一个租户“user”，存储用户服务的消息。该租户可以按自己的业务场景，创建多个命名空间，存放不同的主题，如图1-3所示。
- Cluster集群：Pulsar为集群定义了一个Cluster概念，每个Pulsar Broker节点都运行在一个Cluster集群下，不同的Cluster集群之间可以相互复制数据，从而实现跨地域复制。
- ACK机制：与Kafka类似，Pulsar同样需要完成“Broker存储消息后返回成功响应给生产者”“消费者成功处理消息后发送ACK给Broker”两个操作。Pulsar中的每个消息都有一个消息Id，Pulsar消费者会将消费成功的消息Id作为ACK请求内容发送给Broker。
图1-4展示了Pulsar集群的基础架构。
1.4本章总结
本章介绍了Kafka与Pulsar的起源发展与系统特性，以及Kafka与Pulsar中最基本的核心概念。本书后面会详细介绍这些概念的具体含义与作用，也会逐渐补充Kafka与Pulsar中其他的关键概念，如果读者对某个概念不太理解，则可以先带着疑问继续阅读本书。
本文内容摘自作者新书《深入理解Kafka与Pulsar》，这本书深入分析当前最流行的两个消息流平台Kafka与Pulsar，通过阅读本书，读者可以快速入门和使用Kafka与Pulsar，并深入理解它们的实现原理。感兴趣的朋友可以从这里预览书籍：《雀语-深入理解Kafka与Pulsar》
笔者最新书籍《Redis核心原理与实践》、《深入理解Kafka与Pulsar》已上市，为了感谢大家的支持，最近五一期间开展抽奖送书活动，感兴趣的朋友可以关注公众号binecy，发送“抽奖Redis”或“抽奖Kafka/Pulsar”，即可参与抽奖哦，谢谢大家支持