消息积压:业务突然增长,导致消息消费不过来怎么办?

消息积压:业务突然增长,导致消息消费不过来怎么办?

消息积压指消息生产速度大于消费速度,导致消息在broker上存放。消息积压可能导致消息很久才被消费。对于时效性有要求的业务是不可容忍的。

消费者和分区的关系

  • Kafka中,一个分区只能有一个消费者,但一个消费者可以同时消费多个分区。
  • 如果有N个分区,最多有N个消费者,再增加消费者也不能提供消费速度
  • 如果不足N个消费者,一些消费者会从多个分区拉数据

这种设计无法通过无限增加消费者来解决消息积压问题。如果没有这种限制就不会有消息积压了

确定分区数量

  • 分区数量要保证生产者不会阻塞,同时消费者来的及消费消息
  • 可以通过压测或者观测消息集群性能来确定

解决方案

解决消息积压要区分是临时积压还是永久积压

  • 临时积压:是突然来的流量,导致消费者一时半会跟不上
  • 永久积压:则是消费者消费速率跟不上生产速率
  • 如果临时积压,并且消费者处理的时间可以接受,可以不解决
  • 如果接受不了,或是永久积压。就需要尝试解决。最简单的方案是增加消费者到分区数量一致

增加分区

如果消费者和分区数量一致可以尝试增加分区。

  • 增加新分区意味着可以增加新的消费者来增速

创建新的topic

有时候公司不允许增加分区,可以考虑创建新的topic

  • 准备一个新topic,消费老topic的同时也消费新的topic。等老topic数据消费完后完全切换到新topic
  • 或者创建新topic,把老topic上的消息转发到新topic上。只需要启动消费者消费新topic就可以了

创建新topic的难点是究竟需要几个分区,最佳办法就是压测来确定

新分区计算方式:假设所有生产者QPS是3000。一个消费者处理的QPS是200,那么就是3000÷200=15。考虑业务增长或者突发流量可以使用18到20个分区

优化消费者性能

不能增加消费者和分区的时候,可以考虑优化消费者性能,大体两种思路

  • 消费者部署更好的实例上(不是我们能左右的)
  • 优化消费者消费逻辑
方案
  • 最开始考虑同一个业务的消息可能被不同的消费者消费,就引入了分布式锁
  • 后面通过主动选择目标分区使相同业务总把消息发到同一分区,确保同一时间只有一个消费者处理一个业务的消息,就可以去掉分布式锁,没有分布式锁就不会因为等待分布式锁而导致消费速率下降

聚合消息和批量操作

  • 这种方式适用于消费者可以改造成批量接口的场景
  • 可以考虑不改造生产者,只改造消费者
  • 把消费者改造成批量消费、批量提交偏移量
  • 比如消费者一次性拉去100条消息,构造批量处理请求。请求处理成功后,再提交偏移量

异步消费(核心解决方案)

  • 消费者弄一个消费线程,负责从消息队列拉消息。拉到的消息立刻转发给一个线程池,线程池有一些工作线程处理消息。
  • 注意消息丢失的问题
消息丢失
  • 消息丢失:指消费者线程取出消息后,要消费下一条就要先提交当前这条。这时可能出现一个问题:消费者线程提交了,但是工作线程还没处理就挂了。因为已经提交了,就算重启也是从下一条开始消费
  • 解决方案:可以考虑批量提交的方法。消费者线程一次拉一批消息。比如说10条,然后不是立刻提交这10条消息,而是开十个线程并行处理这10条消息,等10条消息都处理完,再批量提交
  • 问题:批量提交效果很好,但是会带来重复消费和部分失败的问题
重复消费

消费者线程拉去一批消息后,如果还没提交就挂了。当消费者恢复后,就会拉取同一批继续消费。

  • 解决方案:保证处理消息的逻辑是幂等的。这样即使宕机导致消费被消费还没提交,也可以保证下次恢复时,重复处理不会引起业务问题
部分失败

要保证部分失败不会影响继续向前消费

  • 第一种做法是要求工作线程立即重试。比如重试三次,或者用一个新的异步线程来重试
  • 第二种做法是把消费失败的消息丢回消息队列,后面轮到它又会被处理,相当于重试
相关推荐
wuxuanok1 小时前
Web后端开发-分层解耦
java·笔记·后端·学习
31535669131 小时前
ClipReader:一个剪贴板英语单词阅读器
前端·后端
ladymorgana1 小时前
【Spring Boot】HikariCP 连接池 YAML 配置详解
spring boot·后端·mysql·连接池·hikaricp
neoooo2 小时前
别慌,Java只有值传递——一次搞懂“为啥我改了它还不变”!
java·后端·spring
用户7785371836962 小时前
一力破万法:从0实现一个http代理池
后端·爬虫
腾讯云中间件2 小时前
TDMQ RocketMQ 版事务消息原理解析
消息队列·rocketmq·腾讯
拖孩2 小时前
微信群太多,管理麻烦?那试试接入AI助手吧~
前端·后端·微信
Humbunklung2 小时前
Rust枚举:让数据类型告别单调乏味
开发语言·后端·rust
CodeWithMe2 小时前
【Note】《Kafka: The Definitive Guide》 第8章: Cross-Cluster Data Mirroring
分布式·kafka
radient2 小时前
Golang-GMP 万字洗髓经
后端·架构