消息中间件 Kafka

2024-06-23 15:48
文章标签 kafka 消息中间件

本文主要是介绍消息中间件 Kafka,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

假设一种case,一个任务耗时高达数十秒,使用同步方式调用,一言不合便是超时,这可如何是好呢?

首相想到的,当然是异步化。耗时巨大的任务,使用同步调用方式,比如HTTP或者RPC,超时是很难避免的了。一个更好的做法便是将任务放入一个队列,同时给这个任务赋予一个唯一标识符,根据这个唯一标识符去获取任务的结果。队列有许多种,比如著名的Kafka,Nsq,RabbitMq等等。不同的队列有着不一样的适用场景。

笔者今天来谈谈对Kafka这一消息中间件的理解。

Kafka可以说是当前最为完善,使用最广泛的消息中间件。Kafka底层使用Scala语言编写,运行时需要JVM环境支撑。Kafka通常需要与Zookeeper一同使用,Kafka集群信息存储于Zookeeper中,每当有新的实例加入或者旧的实例退出时,都会在Zookeeper中进行实例信息的更改。Kafka 0.9之前的版本还会将offset存储于Zookeeper中,0.9版本及之后,offset不再存储于Zookeeper中,而改成存储在broker实例中。关于Kafka的offset将会在下文中阐述,这也是Kafka最为重要的一个概念。

说说Kafka最基本的几个概念。

Producer(生产者)

消息队列的生产者端,也就是发消息的。生产者发送消息的时候,会指定发送到哪个topic。

Consumer(消费者)

消息队列的消费者端。消费者会订阅某个topic,它会接收到来自这个topic的消息。

Consumer Group(消费者组)

字面意思,消费者的组。对于同一个消费者组,组内会有多个消费者进程,一个消费者对应一个消费者进程。对于归属于同一组的消费者,此消费者组订阅了一个topic,那么,来自这个topic的消息只会被消费者组中的一个消费者进程消费,如图Figure1所示。

消息中间件 Kafka

Figure1

对于两个不同的消费者组,这两个消费者组订阅了同一个topic,那么,来自这个topic的消息对于这两个消费者组是广播的,如图Figure1所示。

Topic(主题)

上文中已提到。不同的topic之间是相互独立开的,不同的topic里面存放着不同的消息。通常一个Kafka队列会有多个不同的业务方接入,不同的业务方使用不同的topic相互之间完全隔离。

Partition(分区)

对于一个topic,里面有一个或者多个分区。生产者发送的消息进入到topic里面之后,会均匀的分布在不同的分区之中,如图Figure2所示。

消息中间件 Kafka

Figure2

对于同一个分区内部,消息是保持有序的,但是在有多个分区的情况下,topic整体上消息无序。因此,如果有什么业务场景要求消息保持绝对有序,一定要将分区数量设置为1。对于同一个消费者组内部,一个消费者进程可以消费一个或者多个分区的消息。如果消费者进程数量小于分区数量,那么一个进程消费多个分区;如果消费者进程数量大于分区数量,那么就会有进程被闲置,因为一个分区只能被一个消费者消费。因此,通常设置同一个消费者组内,消费者数量等于分区数量,此时能够达到最高吞吐量。

Broker(实例,也就是机器)

Kafka通常由集群构成,集群中的一台机器,也就是一台实例,就是一个broker。

Offset(偏移量,用于记录当前消费位置)

笔者认为,这是kafka中最为关键的一个概念。Kafka队列的原理是,生产者写入的消息会保存到本地磁盘文件,也就是说,生产者发送的所有的消息都会被保存下来。消费者消费消息时,消息不是真的被消费了,而是,消费一条消息之后,offset向后偏移一位,指向下一条消息的index,如图Figure3所示。

消息中间件 Kafka

Figure3

在Figure3中,生产者从左侧写入消息,消费者的offset从右侧开始消费偏移。图中所示的是一个partition内部的情况,对于一个完整的topic,每个partition都会为每一个消费者组维持着一个offset值。什么意思呢?对于一个消费者组,它订阅了一个topic,也就是说,它正在消费这个topic中的所有partition,每个partition中都为这个消费者组,维护着一份offset,来表明该消费者组在这个partition中消费到了什么位置。当这个topic有多个消费者组订阅时,partition就会为每一个消费者组维护一份offset,因为不同的消费者组消费到的位置不一样。Offset不是永远只会往后移动的,他是可以自定义调整位置的。只要生产者成功写入了消息,消息就会被Kafka保存下来。如果消费者因为一些原因没能消费成功,那么可以通过修改偏移量offset来重新进行一次消费。在一些精确度要求很高的场景,这种特性十分适用,比如计费,点钞票的时候因为一些原因点漏了可就不好了,Kafka存储了所有消息,就算出现了异常,通过修改offset重来一次就好了。

那么,有个问题,对于同一个消费者组内部,每个消费者进程,是怎样被分配给topic里面的partition的呢?

分配策略有很多,笔者在这里说说Kafka本身自带的默认的两种策略,他们是RangeRoundRobin

Range策略

该策略十分简单。假设现在有1~10合计10个分区,有1~3合计三个消费者进程。此时我们用 10 除以 3,得到3余1。对于三个消费者进程,我们先分别给3个消费者进程分配3个分区。此时还有一个分区,我们将其分配给第一个消费者。于是乎,分区分配情况就是【(1, 2, 3, 4), (5, 6, 7), (8, 9, 10)】。第一个消费者进程分陪了1~4号分区,第二个消费者进程分配了5~7号分区,第三个消费者进程分配了8~10号分区。

再举一个例子,假设现在有1~11合计11个分区,有1~3合计三个消费者进程。那么11除以3等于3余2。先平均分配,此时剩余2个分区,我们再将这两个分区分配给前面的两个消费者进程,也就是【(1,2,3,4),(5,6,7,8),(9,10,11)】。

RoundRobin策略

该策略会无视Kafka的topic,它会将topic+partition视为一个整体,随后计算其hashcode,根据计算出来的hashcode值,对所有的topic-partition进行排序。随后,按照RoundRobin原则,将这些topic-partition均分给所有的消费者进程,如图Figure4所示。

消息中间件 Kafka

Figure4

在只订阅一个topic的情况下,上述两种策略其实没有特别大的区别。然而在订阅了多个topic的情况下,RoundRobin策略将会优于Range策略。Figure5所示为Range策略的一个bad case。

消息中间件 Kafka

Figure5

我们按照Range策略进行了分区分配之后,我们发现,consumer1消费了6个分区,consumer2消费了5个分区,consumer3只消费了三个分区。那么,这种分配就严重不均衡了。但如果是使用了RoundRobin策略,情况就会好的多,因为它将topic-partition视为了一个整体,不会因为topic的缘故导致分配不均匀,如图Figure6所示。

消息中间件 Kafka

Figure6

在RoundRobin策略下,consumer1和consumer2各消费了4个partition,consumer3消费了3个partition,分配情况优于Range策略。

那么当有消费者进程退出或者启动的时候,会发生什么呢?这种情况下,原先的分配就被打乱了吧?

是的,确实被打乱了,此时就会发生重平衡(rebalance)。重平衡发生于消费者进程数量发生变化的时候,为了保持分区分配的合理性,需重新进行一次分区分配。重平衡进行的时候,消费者暂停消费,不过时间不会太长,有可能导致短暂的服务不可用。如果监测到一个消费者服务频繁地发生重平衡,应当检查服务是否存在存在进程退出的case。

这篇关于消息中间件 Kafka的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1087597

相关文章

常用MQ消息中间件Kafka、ZeroMQ和RabbitMQ对比及RabbitMQ详解

1、概述   在现代的分布式系统和实时数据处理领域,消息中间件扮演着关键的角色,用于解决应用程序之间的通信和数据传递的挑战。在众多的消息中间件解决方案中,Kafka、ZeroMQ和RabbitMQ 是备受关注和广泛应用的代表性系统。它们各自具有独特的特点和优势,适用于不同的应用场景和需求。   Kafka 是一个高性能、可扩展的分布式消息队列系统,被设计用于处理大规模的数据流和实时数据传输。它

Kafka中的数据本身就是倾斜的,使用FlinkSQL该如何处理

又是经历了一段不太平的变动,最近算是稳定了点,工作内容又从后端开发转换成了sql boy,又要开始搞大数据这一套了。不同的是之前写实时任务的时候都是用的java代码,新环境却更加偏向与使用flink sql 解决,所以记录下使用flink sql 的一些感悟和遇到的问题吧。 查看反压:         如果flink任务是这么一坨或者几坨task组合在一起,有些时候是如法看

搭建大型分布式服务(四十)SpringBoot 整合多个kafka数据源-支持生产者

系列文章目录 文章目录 系列文章目录前言一、本文要点二、开发环境三、原项目四、修改项目五、测试一下五、小结 前言 本插件稳定运行上百个kafka项目,每天处理上亿级的数据的精简小插件,快速上手。 <dependency><groupId>io.github.vipjoey</groupId><artifactId>multi-kafka-starter</ar

# Kafka_深入探秘者(2):kafka 生产者

Kafka_深入探秘者(2):kafka 生产者 一、kafka 消息发送流程解析 1、kafka :java 客户端 数据生产流程解析 二、kafka 发送类型 1、kafka 发送类型–发送即忘记:producer.send(record) 同步发送 //通过 send() 发送完消息后返回一个 Future 对象,然后调用 Future 对象的 get() 方法等待 kafk

linux使用docker部署kafka集群

1、拉取kafka docker pull wurstmeister/kafkadocker pull wurstmeister/zookeeper 2、创建网络 docker network create app-kafka 3、启动zookeeper docker run -d \--name zookeeper \-p 2181:2181 \--network app-kafka

RabbitMQ和Kafka设计思想的感性辨析

RabbitMQ和Kafka架构图 1. 设计初衷不完全相同 RabbitMQ是消息分发中间件 包收包送,服务很周到。 设计初衷:单播,消息一对一,每条消息只会被发送一个消费者(当然也可以扩展,如果想让多个消费者消费同一条消息,就得这条消息复制成多份放到多个Queue)。Kafka是消息存储和订阅中间件 自己放自己取,只负责提供场地,其它的全自助。 设计初衷:广播,消息一对多,凡是

RabbitMQ、ActiveMQ、Kafka比较

系统吞吐量: Kafka > RabbitMQ > ActiveMQ持久化消息(宕机消息不丢失):RabbitMQ > ActiveMQ高并发:RabbitMQ(Erlang语言开发) > ActiveMQ集群负载均衡:Kafka > Rabbit兼容性:ActiveMQ(与Java完美兼容) > RabbitMQ RabbitMQ基于AMQP协议,支持消息持久化,支持可靠传递、支持事务 Ac

kafka(四)消息类型

一、同步消息 1、生产者 同步发送的意思就是,一条消息发送之后,会阻塞当前线程,直至返回 ack。 由于 send 方法返回的是一个 Future 对象,根据 Futrue 对象的特点,我们也可以实现同 步发送的效果,只需在调用 Future 对象的 get 方发即可。 import org.apache.kafka.clients.producer.KafkaProducer;impor

kafka 集群 Controller 节点和 zookeeper 集群 leader 节点有何区别联系?

kafka 集群 Controller 节点和 zookeeper 集群 leader 节点有何区别联系? Kafka 集群中的 Controller 节点和 ZooKeeper 集群中的 Leader 节点在角色和功能上有明显的区 别,但它们之间也有一定的联系。以下是它们的详细区别和联系: Kafka 集群中的 Controller 节点 角色和功能: 管理任务: Kafka Con

kafka 管理节点 Controller 角色分析

kafka 管理节点 Controller 角色分析 kafka controller 如何管理分区的创建、状态监测、故障切换、内容复制、如何管控分区副本的状态检测故障切换、数据同步、learder 选举? Kafka Controller 是 Kafka 集群中的一个关键组件,负责管理分区的创建、状态监测、故障切换、内容 复制等任务。它通过 ZooKeeper 协调和管理这些任务,确保 K