消息队列高手课
李玥
京东零售技术架构部资深架构师
立即订阅
8426 人已学习
课程目录
已完结 41 讲
0/4登录后,你可以任选4讲全文学习。
课前必读 (2讲)
开篇词 | 优秀的程序员,你的技术栈中不能只有“增删改查”
免费
预习 | 怎样更好地学习这门课?
基础篇 (8讲)
01 | 为什么需要消息队列?
02 | 该如何选择消息队列?
03 | 消息模型:主题和队列有什么区别?
04 | 如何利用事务消息实现分布式事务?
05 | 如何确保消息不会丢失?
06 | 如何处理消费过程中的重复消息?
07 | 消息积压了该如何处理?
08 | 答疑解惑(一) : 网关如何接收服务端的秒杀结果?
进阶篇 (21讲)
09 | 学习开源代码该如何入手?
10 | 如何使用异步设计提升系统性能?
11 | 如何实现高性能的异步网络传输?
12 | 序列化与反序列化:如何通过网络传输结构化的数据?
13 | 传输协议:应用程序之间对话的语言
14 | 内存管理:如何避免内存溢出和频繁的垃圾回收?
加餐 | JMQ的Broker是如何异步处理消息的?
15 | Kafka如何实现高性能IO?
16 | 缓存策略:如何使用缓存来减少磁盘IO?
17 | 如何正确使用锁保护共享数据,协调异步线程?
18 | 如何用硬件同步原语(CAS)替代锁?
19 | 数据压缩:时间换空间的游戏
20 | RocketMQ Producer源码分析:消息生产的实现过程
21 | Kafka Consumer源码分析:消息消费的实现过程
22 | Kafka和RocketMQ的消息复制实现的差异点在哪?
23 | RocketMQ客户端如何在集群中找到正确的节点?
24 | Kafka的协调服务ZooKeeper:实现分布式系统的“瑞士军刀”
25 | RocketMQ与Kafka中如何实现事务?
26 | MQTT协议:如何支持海量的在线IoT设备?
27 | Pulsar的存储计算分离设计:全新的消息队列设计思路
28 | 答疑解惑(二):我的100元哪儿去了?
案例篇 (7讲)
29 | 流计算与消息(一):通过Flink理解流计算的原理
30 | 流计算与消息(二):在流计算中使用Kafka链接计算任务
31 | 动手实现一个简单的RPC框架(一):原理和程序的结构
32 | 动手实现一个简单的RPC框架(二):通信与序列化
33 | 动手实现一个简单的RPC框架(三):客户端
34 | 动手实现一个简单的RPC框架(四):服务端
35 | 答疑解惑(三):主流消息队列都是如何存储消息的?
测试篇 (2讲)
期中测试丨10个消息队列热点问题自测
免费
期末测试 | 消息队列100分试卷等你来挑战!
结束语 (1讲)
结束语 | 程序员如何构建知识体系?
消息队列高手课
登录|注册

07 | 消息积压了该如何处理?

李玥 2019-08-06
你好,我是李玥。这节课我们来聊一聊关于消息积压的问题。
据我了解,在使用消息队列遇到的问题中,消息积压这个问题,应该是最常遇到的问题了,并且,这个问题还不太好解决。
我们都知道,消息积压的直接原因,一定是系统中的某个部分出现了性能问题,来不及处理上游发送的消息,才会导致消息积压。
所以,我们先来分析下,在使用消息队列时,如何来优化代码的性能,避免出现消息积压。然后再来看看,如果你的线上系统出现了消息积压,该如何进行紧急处理,最大程度地避免消息积压对业务的影响。

优化性能来避免消息积压

在使用消息队列的系统中,对于性能的优化,主要体现在生产者和消费者这一收一发两部分的业务逻辑中。对于消息队列本身的性能,你作为使用者,不需要太关注。为什么这么说呢?
主要原因是,对于绝大多数使用消息队列的业务来说,消息队列本身的处理能力要远大于业务系统的处理能力。主流消息队列的单个节点,消息收发的性能可以达到每秒钟处理几万至几十万条消息的水平,还可以通过水平扩展 Broker 的实例数成倍地提升处理能力。
而一般的业务系统需要处理的业务逻辑远比消息队列要复杂,单个节点每秒钟可以处理几百到几千次请求,已经可以算是性能非常好的了。所以,对于消息队列的性能优化,我们更关注的是,在消息的收发两端,我们的业务代码怎么和消息队列配合,达到一个最佳的性能。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《消息队列高手课》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(53)

  • 约书亚
    批量消费有意义的场景要求:1.要么消费端对消息的处理支持批量处理,比如批量入库 2. 要么消费端支持多线程/协程并发处理,业务上也允许消息无序。3. 或者网络带宽在考虑因素内,需要减少消息的overhead。
    批量消费的局限性:1. 需要一个整体ack的机制,一旦一条靠前的消息消费失败,可能会引起很多消息重试。2. 多线程下批量消费速度受限于最慢的那个线程。
    但其实以上局限并没有影响主流MQ的实现了批量功能。
    2019-08-06
    2
    22
  • 岁月安然
    1、要求消费端能够批量处理或者开启多线程进行单条处理
    2、批量消费一旦某一条数据消费失败会导致整批数据重复消费
    3、对实时性要求不能太高,批量消费需要Broker积累到一定消费数据才会发送到Consumer

    作者回复: 👍👍👍

    2019-08-06
    15
  • C J J
    一、如何预防消息积压?
    1、发送端提高并发及批量大小;
    2、消费端增加实例且同步宽容分区;

    二、如何处理消息积压?
    1、消费端扩容;
    2、服务降级;
    3、异常监控。
    2019-08-08
    12
  • iLeGeND
    老师好,我一直理解,消息积压不是一种正常的现象吗?来不及处理的消息先在消息队列中存着,缓解下游系统的压力,让上下游系统在时间上解偶,,听了今天的课,感觉理解的不太一样,希望老师解答一下

    作者回复: 消息积压是正常现象,积压越来越多就需要处理了。

    就像一个水库,日常蓄水是正常的,但下游泄洪能力太差,导致水库水位一直不停的上涨,这个就不正常了。

    2019-08-06
    1
    12
  • linqw
    尝试回答下课后习题,老师有空帮忙看下哦
    消费端进行批量操作,感觉和上面的先将消息放在内存队列中,然后在并发消费消息,如果机器宕机,这些批量消息都会丢失,如果在数据库层面,批量操作在大事务,会导致锁的竞争,并且也会导致主备的不一致。如果是一些不重要的消息如对日志进行备份,就可以使用批量操作之类的提高消费性能,因为一些日志消息丢失也是可以接受的。

    作者回复: 非常好!

    2019-08-06
    6
  • 蓝魔丶
    消费端通过丢入队列,并使用多线程来提高并发,老师讲到可能丢消息,但也要是某种条件成立,比如开启了自动提交,如果改为手动提交完全可以避免丢消息,只是可能出现重复消费问题,至少不会丢
    2019-08-06
    3
    3
  • Jxin
    1.无法提升消费业务效率(仅受消费业务自身逻辑影响),但可以提高mq中堆积消息消费的整体吞吐量(批推比单推mq耗时较短)。
    2.数据增量同步,监控信息采集。(非核心业务的稳定大数据流操作)。
    3.批处理意味数据积累和大数据传输,这会让单次消费的最长时延变长。同时批量操作为了保证当前批量操作一致性,在个别失败的情况下会引发批量操作重试。

    作者回复: 总结的非常好!

    2019-08-06
    3
  • 天涯煮酒
    一开始不理解为啥Producer发得慢了会导致消息积压,明明是发得少了Broker端的消息应该更少啊

    后来想到前面章节有提到消息事务,Producer首先会开启事务并发送一个半消息,再执行业务逻辑,最后提交事务,如果发得慢了会导致半消息在Broker中的时间增长,导致积压
    2019-09-06
    1
    2
  • lecy_L
    消息积压处理:
    1、发送端优化,增加批量和线程并发两种方式处理
    2、消费端优化,优化业务逻辑代码、水平扩容增加并发并同步扩容分区数量
    查看消息积压的方法:
    1、消息队列内置监控,查看发送端发送消息与消费端消费消息的速度变化
    2、查看日志是否有大量的消费错误
    3、打印堆栈信息,查看消费线程卡点信息

    作者回复: 👍👍👍

    2019-08-16
    2
  • 13761642169
    消息本来就有限流或者削峰填谷,这个也是使用消息队列的作用,老师您讲的不严谨。
    2019-08-09
    2
  • 长期规划
    老师,如果onMessage方法中,收到消息后不确认,等真正处理完消息再确认,就可以了吧,这样就可以用内存队列了

    作者回复: 理论上是可以的,但你要注意,像RocketMQ,采用默认配置的时候,onMessage方法结束后,如果没抛异常,默认就会自动确认了。

    2019-09-02
    1
  • grey927
    发送端如果多线程,如何实现之前您在《确保消息不会丢失》这篇文章中说的:
    发送端 把发送消息标识为每次增加1的效果?

    作者回复: 可以使用一个自增的原子变量,比如Java中的AtomicLong。

    2019-08-26
    1
  • godtrue
    1:请教几个小问题
    1-1:目前那些消息队列产品实现了批量消费?
    1-2:批量消费的实现原理是怎用的?类似文中的例子直接放入一个内存队列中,然后再开启多线程批量消费嘛?

    2:课后思考
    2-1:在消费端是否可以通过批量消费的方式来提升消费性能?
    可以
    2-2:在什么样场景下,适合使用这种方法?
    不担心重复消费,网络环境比较稳定,消费者端机器比较稳定
    2-3:这种方法有什么局限性?
    首先,使用的消息队列产品支持批量消费
    然后,一次取多条消息,性能节省在连接建立上,消息量大在传输时会多耗一点,且消息者只能消费完一批消息,才能返回确认,会耽误点时间取下一批消息
    最后,如果一批消息的消费过程中有一个失败了,假如一次消费1000条消息,消费第1000条时失败了,则整批消息都算失败了,那会重试,则前面999条消息都会重复消费,如果都有幂等控制也没什么,不过这种情况会使单台消息消费成功的时间加长许多。

    3:本节小结
    3-1:消息积压怎么产生的?
    要么生产者太快了,要么消费者太慢了,这是相对的,但无论如何根本就是消费者的消费速度<生产者的生产速度。
    3-2:消息积压咋弄?
    3-2-1:就让他积压,不管
    3-2-2:有时为了缓解消费者的压力,还会故意让他积压
    3-2-3:优化消费者逻辑,比如:将慢逻辑移出去,再将消息倒一道手
    3-2-4:扩容,消费者扩容,broker也扩容,保持同一个主题下的分区和消费者实例一一对应,充分发挥消费者的性能
    3-2-5:某些情况可以使消费者侧批量消费消息的方式,来提高性能

    作者回复: 第一个问题,主流的消息队列都有实现,区别是,Kafka它是自动异步批量发送,而其它消息队列会提供一个类似batchSend(Msg [] messages)的批量发送的方法,由使用者决定是否批量发送以及批量大小。

    第二个问题我们后面的课程会有专门的讲解。

    2019-08-21
    1
  • 猿人谷
    在消费端需要注意的是,增加并发需要同步扩容分区数量,否则是起不到效果的。
    这一点非常需要注意,其实有些公司在这个地方用错了。
    2019-08-06
    1
  • 严青
    我没读过这篇文章之前我看过别人面试的解决消息积压的方法:
    (1)临时扩容,增加消费端,用硬件提升消费速度。
    (2)服务降级,关闭一些非核心业务,减少消息生产。
    (3)通过日志分析,监控等找到挤压原因,消息队列三部分,上游生产者是否异常生产大量数据,中游消息队列存储层是否出现问题,下游消费速度是否变慢,就能确定哪个环节出了问题
    (4)根据排查解决异常部分。
    (5)等待积压的消息被消费,恢复到正常状态,撤掉扩容服务器。
    到此,问题解决
    2019-12-02
  • 唯我天棋
    可以,在消费消息量特别大,且消费速度特别快的情况下。需要控制批量数量,太大,太小都不好。
    2019-12-02
  • 攀攀
    老师好 消费端 比如kafka增加机器 不能起到增加消费能力的作用 如果按照多线程来进行消费 在一定量处理完毕之后进行统一的位点提交 这么做可以避免重启后消息丢失的问题 是不是就可以解决消费端的能力扩容问题了

    作者回复: 是的,这个方法理论上是没问题的。实现起来稍微有点儿复杂,只要能正确的实现出来是可以解决问题的。

    2019-11-20
  • 瓦特
    在扩容 Consumer 的实例数量的同时,必须同步扩容主题中的分区(也叫队列)数量,确保 Consumer 的实例数和分区数量是相等的。------------请问在不同主题下,队列数量怎么 设置尼,是某个参数么

    作者回复: 队列的数量一般是在创建主题的时候指定的。

    2019-11-14
  • 张三丰
    下面这句话不太理解,老师这里说的consumor实际上是consumor组,因为每个consumor组是互不影响的,这在一定程度上提升了并发性,所以为何当consumor组超过队列的时候没有意义呢?
    比如,队列a,Consumor组A,Comsumor组B,它们两个可以并发的消费队列a,这提升了性能才对啊。

    “在扩容 Consumer 的实例数量的同时,必须同步扩容主题中的分区(也叫队列)数量,确保 Consumer 的实例数和分区数量是相等的。如果 Consumer 的实例数量超过分区数量,这样的扩容实际上是没有效果的。”

    作者回复: 这里面说的不是consumer group,就是consumer的实例数。关于consumer group的概念,你可以看一下下节课的热点问题解答,里面会有详细的解释。

    2019-10-21
  • 饭团
    因为一个分区只能一个消费者消费!所以如果要实现并发消费需要该消费者向消息队列连续取n次!并确认n次!在战队队列数据收到确认消息后,消息队列的消息消费指针就移动了n次!认为这些消息都被消费了!所以如果这个时候客户端出现异常!这些消息就丢了!所以这种情况适合老师文中提到的日志系统!可以容忍部分日志丢失的情况!
    2019-09-20
收起评论
53
返回
顶部