zookeeper + kafka 消息队列
一、消息队列简介
1、什么是消息队列
消息队列(Message Queue)是一种用于跨进程或分布式系统
中传递消息的通信机制。消息队列在异步通信、系统解耦、负载均衡和容错方面具有重要作用。
(1)特性
-
异步通信:发送方将消息发送到队列中后,不需要等待接收方处理完毕即刻返回继续执行。接收方可以在需要时从队列中读取并处理消息。
-
解耦:消息队列在发送方和接收方之间充当中介,允许它们独立运行。这样,即使其中一个部分暂时不可用,系统的整体功能依然可以保持正常。
-
负载均衡:通过消息队列,多个消费者可以分担消息处理的工作量,提高系统的吞吐量。
-
可靠性:消息队列可以确保消息在传递过程中不丢失,即使在系统出现故障时也能保证消息被妥善处理。
-
扩展性:可以根据需要增加消息生产者或消费者,从而轻松扩展系统。
-
缓冲和流量控制:在高并发的场景下,系统的不同部分可能无法以相同的速度处理请求。消息队列可以作为缓冲区,调节生产者和消费者之间的速度差异,防止系统过载或崩溃。
(2)用途
- 任务队列:在需要异步处理任务的情况下,消息队列非常有用。例如,Web 应用在接收到用户请求后将耗时操作(如视频处理、文件转换)放入队列中,立即返回响应,后续处理由工作线程完成。
- 事件通知:在事件驱动系统中,组件之间可以通过消息队列进行通信和通知。例如,当用户在网站上完成购买操作后,消息队列可以通知库存管理系统更新库存。
- 日志收集:可以将系统中产生的日志消息通过消息队列发送到集中式日志处理系统中,以便进行实时分析和监控。
- 数据流处理:用于处理数据流的系统,如实时分析平台,可以通过消息队列来传递和处理数据。
2、常见的消息队列软件
(1)RabbitMQ
特点:
- 基于AMQP(Advanced Message Queuing Protocol)协议,具有高度灵活性。
- 支持多种消息传递协议,包括 STOMP、MQTT 和 HTTP。
- 提供可靠的消息传递机制,包括消息确认、持久化、发布确认等。
- 支持复杂的路由机制,如使用交换机(Exchanges)和绑定(Bindings)来实现消息路由。
- 易于管理和监控,提供了丰富的管理工具和插件。
用途:
- 企业级应用程序集成。
- 任务调度系统。
- 实时消息通知系统。
优点:
- 功能强大,支持多种协议和复杂的消息路由。
- 稳定性高,适用于企业级应用。
- 良好的文档和社区支持。
缺点:
- 对资源要求较高,配置和维护相对复杂。
- 吞吐量相对较低,不适合高吞吐量的实时数据流处理。
(2)Apache Kafka
特点:
- 分布式流处理平台,提供高吞吐量、低延迟的消息传递。
- 支持持久化,所有消息都被持久化到磁盘上,可以通过配置保留时间。
- 基于发布-订阅模型,消费者可以独立地读取和处理消息。
- 支持分区(Partition)和副本(Replica),保证高可用性和容错性。
- 强大的扩展性,能够轻松扩展以处理大规模数据。
用途:
- 大数据实时处理和分析。
- 日志收集和处理。
- 流式数据处理(如物联网数据、金融交易数据)。
优点:
- 高吞吐量,适合处理大量实时数据。
- 低延迟,消息传递和处理速度快。
- 可扩展性强,适合大规模分布式系统。
缺点:
- 学习曲线较陡,配置和管理相对复杂。
- 消费者需要处理消息的顺序性和幂等性,增加了应用程序的复杂性。
(3)ActiveMQ
特点:
- 基于JMS(Java Message Service)规范的开源消息中间件。
- 支持多种消息传递协议,包括 OpenWire、STOMP、MQTT、AMQP、REST、WebSocket 等。
- 提供丰富的特性,如消息持久化、事务、消息优先级等。
- 易于嵌入 Java 应用程序,支持多语言客户端(如 C++、.NET、Python、Perl、PHP)。
- 提供了管理控制台和监控工具,便于管理和监控消息系统。
用途:
- 企业应用集成。
- 任务调度和自动化流程。
- 消息驱动的微服务架构。
优点:
- 功能全面,支持多种协议和语言。
- 与 Java 应用程序集成良好。
- 社区活跃,文档丰富。
缺点:
- 性能相对较低,不适合高吞吐量的场景。
- 在处理大规模分布式系统时,扩展性有限。
(4)Amazon SQS
特点:
- AWS 提供的完全托管的消息队列服务,无需管理服务器和基础设施。
- 提供标准队列和 FIFO(先入先出)队列,满足不同的消息传递需求。
- 支持自动扩展,能够处理任意数量的消息。
- 与 AWS 生态系统无缝集成,易于与其他 AWS 服务(如 Lambda、S3、SNS)集成。
- 提供消息可见性超时、消息延迟、消息批处理等功能。
用途:
- 分布式系统中的异步任务处理。
- 微服务架构中的消息传递。
- 日志和事件驱动的工作流。
优点:
- 托管服务,无需运维,简单易用。
- 高可用性和可靠性,由 AWS 提供保障。
- 可与 AWS 生态系统中的其他服务轻松集成。
缺点:
- 成本可能较高,特别是在高消息吞吐量的场景中。
- 对于非常高性能和定制化需求的场景,灵活性可能不足。
二、kafka
Apache Kafka 是一个分布式流处理平台,最初由LinkedIn开发,并于2011年成为Apache开源项目。Kafka主要用于构建实时数据管道和流处理应用程序,它具有高吞吐量、低延迟、可扩展性和容错性。
1、kafka 架构
Kafka 的架构主要包括以下几个核心组件:
1. Producer(生产者)
生产者是负责发布消息到 Kafka 主题的客户端。生产者可以选择将消息发送到特定的分区,也可以通过键进行分区路由。
2. Consumer(消费者)
消费者是负责从 Kafka 主题中读取消息的客户端。消费者可以订阅一个或多个主题,并以流的方式处理数据。消费者通常会组成一个消费者组(Consumer Group),每个消费者组可以同时读取和处理消息,实现负载均衡。
3. Broker(代理)
Kafka 集群中的每个服务器称为一个代理(Broker)。每个代理负责接收、存储和转发消息。一个 Kafka 集群通常由多个代理组成,以实现高可用性和容错性。
4. Topic(主题)
- 主题是 Kafka 中数据的分类容器。每个主题可以有多个生产者和消费者。主题可以分为多个分区,每个分区内的消息是有序的,但跨分区的消息顺序不保证。
- 在 Kafka 中,一个代理(Broker)可以承载多个主题(Topic)。具体有多少个主题取决于 Kafka 集群的配置和使用场景。
(1)分区内的顺序性
- 在一个分区内,消息是严格有序的,这意味着消息的生产顺序与消费顺序一致。消费者在消费消息时,按照偏移量顺序读取消息。
(2)跨分区的无序性
- 虽然分区内的消息是有序的,但不同分区之间的消息顺序不保证。跨分区的消息无序性是由于分区是独立的并行处理单元,生产者可以同时向多个分区发送消息,导致整体顺序无法保证。
(3)特征
-
多生产者和多消费者:一个主题可以有多个生产者发布消息,也可以有多个消费者订阅和消费消息。这种特性使得 Kafka 可以轻松实现多对多的数据传递。
-
逻辑分组:主题用于将相同类别的数据进行逻辑分组,便于管理和处理。例如,可以创建一个主题来存储网站的访问日志,另一个主题来存储订单信息。
5. Partition(分区)
分区是 Kafka 中并行处理的基本单元。每个分区在磁盘上是一个日志文件,消息以追加的方式写入。分区提供了高吞吐量和并行处理能力。
(1)特性
- 顺序性:在一个分区内,消息是严格有序的。每条消息都有一个唯一的偏移量(Offset),表示消息在分区中的位置。消费者在消费消息时,会按照偏移量顺序逐条读取消息。
- 并行处理:主题的分区允许 Kafka 在多个服务器上并行处理消息。生产者可以将消息分布到不同的分区,消费者也可以从多个分区并行读取消息,从而实现负载均衡和高吞吐量。
- 副本机制:每个分区可以有多个副本(Replica),其中一个为领导者(Leader),其余为追随者(Follower)。所有的读写操作都由领导者处理,追随者从领导者复制数据。副本机制保证了数据的高可用性和容错性。
6. Zookeeper
Zookeeper 负责存储集群的元数据,如代理信息、分区状态等。它还负责选举 Kafka 集群的控制器,管理分区的副本分配和故障恢复。
2、partition的路由规则与默认策略
(1) Partition 的数据路由规则
-
数据路由规则决定了生产者如何将消息发送到 Kafka Topic 的各个 Partition。Kafka 提供了几种常见的 Partitioning 策略,具体如下:
-
Round-robin(轮询):这是最简单的策略,生产者轮流将消息发送到不同的 Partition。如果所有 Partition 都有相似的负载和数据量,这种策略可以实现基本的负载均衡。但是,它不能保证消息的相关性或有序性。
-
Hash-based(基于哈希):生产者使用消息的某个属性(如 key)计算哈希值,然后根据哈希值将消息路由到对应的 Partition。这种策略可以保证具有相同 key 的消息总是被发送到同一个 Partition,从而保证了这些消息的顺序性。
-
Custom Partitioner(自定义分区器):开发者可以根据自己的需求实现自定义的 Partitioner 接口,来控制消息的分区逻辑。这种方式灵活性最高,可以根据业务需求定义非常复杂的分区逻辑。
(2) 默认的 Partitioning 策略
-
在 Kafka 中,默认的 Partitioning 策略是基于消息的 key 进行哈希分区。具体步骤如下:
-
如果消息有 key,则使用 key 进行哈希计算,然后将哈希值与 Topic 的 Partition 数取模,以确定消息发送到哪个 Partition。
-
如果消息没有 key,则使用轮询策略,即将消息依次发送到每个 Partition,实现简单的负载均衡。
3、消费者组详细介绍
(1)介绍
-
消费者组成员:
- 消费者组由多个消费者实例(Consumer Instance)组成。
- 每个消费者实例通常运行在不同的进程或者不同的计算机上。
-
主题分区分配:
- 消费者组的每个实例会订阅一个或多个主题。
- 每个主题被分为多个分区(Partitions),每个分区只能由消费者组中的一个实例进行消费。
- Kafka 通过分区的分配策略将分区均匀分配给消费者组中的各个实例,确保每个分区只被一个消费者实例消费,但一个消费者实例可以消费多个分区。
-
消费者组协调器:
- Kafka 集群中有一个特殊的 Broker 作为消费者组的协调器(Consumer Group Coordinator)。
- 每个消费者组有一个唯一的消费者组 ID,由协调器管理和分配。
(2)消费者组的工作机制
-
消费者协调与分配:
- 当消费者组中的一个新消费者实例加入或离开时,或者分区发生重新分配时,消费者组的协调器负责重新分配分区给消费者实例。
- 分区的分配基于消费者实例的订阅和分配策略(Partition Assignment Strategy),如范围分配、轮询分配等。
-
消息处理并行性:
- 每个分区内的消息是有序的,而不同分区之间的消息顺序不保证。
- 消费者组中的每个消费者实例在处理分区内的消息时是单线程的,但是多个实例可以并行处理不同分区的消息,从而提高整体的消费吞吐量。
-
消费者偏移提交:
- 消费者组中的每个消费者实例会周期性地提交消费偏移(Offset)到 Kafka 集群,以记录其对消息的消费进度。
- Kafka 提供了自动和手动两种提交偏移的方式,确保消息处理的可靠性和一致性。
(3)消费者组的应用场景
-
消费者组在 Kafka 中有多种应用场景,包括但不限于:
-
并行处理:多个消费者实例并行处理同一主题的消息,提高消费吞吐量和效率。
-
水平扩展:通过增加消费者实例,可以水平扩展消费者组的处理能力,适应大规模数据流的需求。
-
容错和高可用性:当一个消费者实例故障或下线时,协调器会重新分配其负责的分区给其他实例,确保消息的连续性和可用性。
4、偏移量详细介绍
(1)偏移量概念
-
偏移量是一个64位的整数,用来唯一标识消费者在一个特定分区中已经消费过的消息位置。每个消费者都会为每个分区维护一个偏移量。偏移量的作用包括:
-
消费位置的记录:偏移量表示消费者已经处理并成功提交的消息位置。消费者会定期地更新偏移量,以记录自己的消费进度。
-
消息处理的顺序性:Kafka 保证每个分区内的消息顺序,消费者通过记录偏移量来确保消息的有序消费,避免重复消费或消息丢失。
-
消费者的恢复:如果消费者实例停止或重启,它可以利用存储的偏移量来恢复消费位置,从上次离开的地方继续消费,而不会丢失消息。
(2)偏移量的管理方式
在 Kafka 中,偏移量的管理可以通过以下几种方式实现:
- 自动提交偏移量:
- 消费者可以选择开启自动提交偏移量的功能,Kafka 将定期(根据配置的间隔)自动将消费者的偏移量提交到 Kafka 集群中。
- 这种方式简单方便,但可能会因为提交频率不合适而导致消息的重复消费或丢失。
- 手动提交偏移量:
- 消费者可以显式地在适当的时候手动提交当前的偏移量。
- 手动提交偏移量可以精确地控制偏移量的提交时机,避免自动提交可能出现的问题,如重复消费或消息丢失。
- 偏移量存储:
- 消费者通常会将偏移量存储在外部系统中,如数据库或文件系统。这样做的好处是,即使消费者实例重新启动或扩展,也能够方便地恢复之前的消费进度。
(3)偏移量的生命周期
偏移量的生命周期包括:
- 消费者组内偏移量管理:
- 每个消费者组内的每个消费者实例会独立地管理自己负责的分区的偏移量。
- 每次消费者处理完消息后,会更新并提交偏移量。这个过程可以是自动的ÿ