场景题:如何提升Kafka效率?
mhr18 2024-12-12 11:51 23 浏览 0 评论
Kafka 以其高吞吐量、低延迟和可扩展性而备受青睐。无论是在实时数据分析、日志收集还是事件驱动架构中,Kafka 都扮演着关键角色。
但是,如果 Kafka 使用不当,也可能会面临性能瓶颈,影响系统的整体效率。所以,了解如何提升 Kafka 的运行效率?对于生产环境的使用和面试都是至关重要的。
那么,提升 Kafka 性能的有效手段都有哪些呢?接下来,我们一起来看。
性能调优主要手段
Kafka 性能调优的主要手段有以下几个:
- 分区扩展
- 消息批发送(重要)
- 消息批获取(重要)
- 配置调优
- JVM 调优
1.分区扩展
在 Kafka 架构中,使用多分区(Partition)来实现数据分片功能。也就是 Kafka 会将多条消息并发存储到一个主题(Topic)的多个 Broker(Kafka 服务)中的多个 Partition 中,以实现并行操作的功能,极大地提高了整体系统的读写能力,如下图所示:
数据分片是一种技术将大数据分割成更小、更易于管理的片段(称为“分片”),并将分片都存储在不同的服务器上,从而实现了数据的水平拆分。通过数据分片,可以有效地解决单一数据库的性能瓶颈、存储限制以及高可用性等问题。
因此,增加更多的 Broker,扩展更多的分区 Partition 是提升 Kafka 性能的关键,如下图所示:
2.消息批发送(重要)
Kafka 默认是不支持批量发送消息的,然而开启批量发送消息可以提升 Kafka 整体运行效率。
为什么要批量发送消息?
批量发送消息有以下优点:
- 减少网络开销:当生产者发送消息给 Kafka 时,如果每次只发送一条消息,那么就需要建立一次 TCP 连接,这涉及到三次握手的过程。而如果采用批量发送的方式,则可以在一次 TCP 连接中发送多条消息,减少了网络连接建立和断开的次数,从而降低了网络开销。
- 减少 I/O 操作:批量发送意味着一次写入操作可以处理更多的数据。这对于磁盘 I/O 来说是一个优势,因为一次大的写操作比多次小的写操作更高效。
- 提高吞吐量:由于减少了通信次数,批量发送可以提高单位时间内发送的消息数量,即提高了吞吐量。
那么,想要实现 Kafka 批量消息发送只需要正确配置以下 3 个参数即可:
- batch-size:定义了 Kafka 生产者尝试批量发送的消息的最大大小(以字节为单位),生产者收集到足够多的消息达到这个大小时,它会尝试发送这些消息给 Kafka Broker,默认值为 16KB。
- buffer-memory:指定了 Kafka 生产者可以用来缓冲待发送消息的总内存空间,如果生产者试图发送的消息超过了这个限制,生产者将会阻塞,直到有足够空间可用或者消息被发送出去,默认值为 32MB。
- linger.ms:生产者在尝试发送消息前等待的最长时间(以毫秒为单位)。默认情况下,linger.ms 的值为 0,这意味着立即发送。
以上 3 个参数满足任一个都会立即(批量)发送。
因此我们如果需要匹配发送,主要需要调整的参数是 linger.ms,如下配置所示:
spring:
kafka:
bootstrap-servers: localhost:9092 # Kafka服务器地址
consumer:
group-id: my-group # 消费者组ID
auto-offset-reset: earliest # 自动重置偏移量到最早的可用消息
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer # 键的反序列化器
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer # 值的反序列化器
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer # 键的序列化器
value-serializer: org.apache.kafka.common.serialization.StringSerializer # 值的序列化器
batch-size: 16384
buffer-memory: 33554432
properties:
linger:
ms: 2000
3.消息批获取(重要)
Kafka 默认每次拉取一条消息,而使用批量获取消息可以有效提升 Kafka 运行效率。
为什么要批量获取消息?
批量获取消息有以下优点:
- 降低客户端处理开销:对于客户端来说,每次处理一个消息需要进行一系列的操作,如解包、解析、处理逻辑等。如果每次只拉取一个消息,客户端会频繁地进行这些操作,带来较大的处理开销。而批量拉取消息时,客户端可以一次性处理多个消息,减少了处理单个消息的频率,从而降低了客户端的处理开销。
- 减少网络往返次数:每次拉取一个消息时,客户端需要与 Kafka 服务器进行多次网络往返,包括发送请求、接收响应等。这些网络往返会带来一定的延迟。而批量拉取消息时,客户端可以一次性拉取多个消息,减少了网络往返的次数,从而降低了网络延迟。
- 优化内存使用:批量拉取消息可以更好地规划和利用内存。客户端可以一次性分配足够的内存来存储批量拉取的消息,避免了频繁地分配和释放小内存块的操作。这样可以提高内存的使用效率,减少内存碎片的产生,进而提升系统的运行效率。
- 提高吞吐量:批量拉取消息可以提高单位时间内处理的消息数量,从而提升了 Kafka 的吞吐量。
想要实现批量读取数据需要做以下两步调整:
- 在配置文件中设置批读取:
spring.kafka.listener.type=batch
- 消费者使用 List<ConsumerRecord<?, ?>> 接收消息,具体实现代码如下:
@KafkaListener(topics = TOPIC)
public void listen(List<ConsumerRecord<?, ?>> consumerRecords) {
for (int i = 0; i < consumerRecords.size(); i++) {
System.out.println("监听到消息:" + consumerRecords.get(i).value());
}
System.out.println("------------end------------");
}
以上程序的执行结果如下:
从执行结果可以看出:只有一个“end”打印,这说明 Kafka 一次拉取了一批数据,而不是一个数据,否则就会有多个“end”。
4.配置调优
合理设置 Kafka 的配置也可以一定程度的提升 Kafka 的效率,例如以下这些配置:
- 配置文件刷盘策略:调整 flush.ms 和 flush.messages 参数,控制数据何时写入磁盘。较小的值可以降低延迟,而较大的值可以提高吞吐量。
- 网络和 IO 操作线程配置优化:num.network.threads 应该设置为 CPU 核心数加 1,以充分利用硬件资源。调整 socket.send.buffer.bytes 和 socket.receive.buffer.bytes 以优化网络缓冲区大小,缓冲区越大,吞吐量也越高。
5.JVM 调优
因为 Kafka 是用 Java 和 Scala 两种语言编写的,而 Java 和 Scala 都是运行在 JVM 上的,因此保证 JVM 的高效运行,设置合理的垃圾回收器,也能间接的保证 Kafka 的运行效率。例如,对于大内存机器,可以使用 G1 垃圾收集器来减少 GC 暂停时间,并为操作系统留出足够的内存用于页面缓存。
课后思考
除了以上手段之后,我们还可以使用消息压缩等手段提升 Kafka 的运行效率。那么问题来了,如何开启 Kafka 的消息压缩?如何设置消息的压缩级别?
本文已收录到我的面试小站 [www.javacn.site](https://www.javacn.site),其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。
相关推荐
- 订单超时自动取消业务的 N 种实现方案,从原理到落地全解析
-
在分布式系统架构中,订单超时自动取消机制是保障业务一致性的关键组件。某电商平台曾因超时处理机制缺陷导致日均3000+订单库存锁定异常,直接损失超50万元/天。本文将从技术原理、实现细节、...
- 使用Spring Boot 3开发时,如何选择合适的分布式技术?
-
作为互联网大厂的后端开发人员,当你满怀期待地用上SpringBoot3,准备在项目中大显身手时,却发现一个棘手的问题摆在面前:面对众多分布式技术,究竟该如何选择,才能让SpringBoot...
- 数据库内存爆满怎么办?99%的程序员都踩过这个坑!
-
你的数据库是不是又双叒叕内存爆满了?!服务器监控一片红色警告,老板在群里@所有人,运维同事的电话打爆了手机...这种场景是不是特别熟悉?别慌!作为一个在数据库优化这条路上摸爬滚打了10年的老司机,今天...
- springboot利用Redisson 实现缓存与数据库双写不一致问题
-
使用了Redisson来操作Redis分布式锁,主要功能是从缓存和数据库中获取商品信息,以下是针对并发时更新缓存和数据库带来不一致问题的解决方案1.基于读写锁和删除缓存策略在并发更新场景下,...
- 外贸独立站数据库炸了?对象缓存让你起死回生
-
上周黑五,一个客户眼睁睁看着服务器CPU飙到100%——每次页面加载要查87次数据库。这让我想起2024年Pantheon的测试:Redis缓存能把WooCommerce查询速度提升20倍。跨境电商最...
- 手把手教你在 Spring Boot3 里纯编码实现自定义分布式锁
-
为什么要自己实现分布式锁?你是不是早就受够了引入各种第三方依赖时的繁琐?尤其是分布式锁这块,每次集成Redisson或者Zookeeper,都得额外维护一堆配置,有时候还会因为版本兼容问题头疼半...
- 如何设计一个支持百万级实时数据推送的WebSocket集群架构?
-
面试解答:要设计一个支持百万级实时数据推送的WebSocket集群架构,需从**连接管理、负载均衡、水平扩展、容灾恢复**四个维度切入:连接层设计-**长连接优化**:采用Netty或Und...
- Redis数据结构总结——面试最常问到的知识点
-
Redis作为主流的nosql存储,面试时经常会问到。其主要场景是用作缓存,分布式锁,分布式session,消息队列,发布订阅等等。其存储结构主要有String,List,Set,Hash,Sort...
- skynet服务的缺陷 lua死循环
-
服务端高级架构—云风的skynet这边有一个关于云风skynet的视频推荐给大家观看点击就可以观看了!skynet是一套多人在线游戏的轻量级服务端框架,使用C+Lua开发。skynet的显著优点是,...
- 七年Java开发的一路辛酸史:分享面试京东、阿里、美团后的心得
-
前言我觉得有一个能够找一份大厂的offer的想法,这是很正常的,这并不是我们的饭后谈资而是每个技术人的追求。像阿里、腾讯、美团、字节跳动、京东等等的技术氛围与技术规范度还是要明显优于一些创业型公司...
- mysql mogodb es redis数据库之间的区别
-
1.MySQL应用场景概念:关系型数据库,基于关系模型,使用表和行存储数据。优点:支持ACID事务,数据具有很高的一致性和完整性。缺点:垂直扩展能力有限,需要分库分表等方式扩展。对于复杂的查询和大量的...
- redis,memcached,nginx网络组件
-
1.理解阻塞io,非阻塞io,同步io,异步io的区别2.理解BIO和AIO的区别io多路复用只负责io检测,不负责io操作阻塞io中的write,能写多少是多少,只要写成功就返回,譬如准备写500字...
- SpringBoot+Vue+Redis实现验证码功能
-
一个小时只允许发三次验证码。一次验证码有效期二分钟。SpringBoot整合Redis...
- AWS MemoryDB 可观测最佳实践
-
AWSMemoryDB介绍AmazonMemoryDB是一种完全托管的、内存中数据存储服务,专为需要极低延迟和高吞吐量的应用程序而设计。它与Redis和Memcached相似,但具有更...
- 从0构建大型AI推荐系统:实时化引擎从工具到生态的演进
-
在AI浪潮席卷各行各业的今天,推荐系统正从幕后走向前台,成为用户体验的核心驱动力。本文将带你深入探索一个大型AI推荐系统从零起步的全过程,揭示实时化引擎如何从单一工具演进为复杂生态的关键路径。无论你是...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle主从同步 (56)
- oracle 乐观锁 (53)
- redis 命令 (83)
- php redis (97)
- redis 存储 (67)
- redis 锁 (74)
- 启动 redis (73)
- redis 时间 (60)
- redis 删除 (69)
- redis内存 (64)
- redis并发 (53)
- redis 主从 (71)
- redis同步 (53)
- redis结构 (53)
- redis 订阅 (54)
- redis 登录 (62)
- redis 面试 (58)
- redis问题 (54)
- 阿里 redis (67)
- redis的缓存 (57)
- lua redis (59)
- redis 连接池 (64)