- 如何监控消息延迟
- 减少消息延迟的正确姿势
- 总结
我们知道了如何使用消息队列应对秒杀时的峰值流量已经有所了解。当然了,你也应该知道要如何做,才能保证消息不会丢失,尽量避免消息 重复带来的影响。那么我们在使用消息队列时:除了这些内容,还需要关注哪些点呢?
先来看一个场景:在我们的电商项目中,会在用户下单支付之后,向消息队列里面发送 一条消息,队列处理程序消费了消息后,会增加用户的积分,或者给用户发送优惠券。那么用户在下单之后,等待几分钟或者十几分钟拿到积分和优惠券是可以接受的,但是一旦消息队列出现大量堆积,用户消费完成后几小时还拿到优惠券,那就会有用户投诉了。
这时,就要关注的就是消息队列中,消息的延迟了,这其实是消费性能的问题,那么要如何提升消费性能,保证更短的消息延迟呢?在我看来,首先需要掌握如何来监控消息的延迟,因为有了数据之后,才可以知道目前的延迟数据是否满足要求,也可以评估优化之后的效果。然后,要掌握使用消息队列的正确姿势,以及关注消息队列本身是如何保证消息尽快被存储和投递的。
如何监控消息延迟监控消息的延迟有两种方式:
-
使用消息队列提供的工具,通过监控消息的堆积来完成
当然,作为一个成熟的组件,很多消息队列产品提供了一些工具来获取这个消费进度的信息,帮助我们实现自己的监控。
-
通过生成监控消息的方式来监控消息的延迟情况
我们定义一种特殊的消息,然后启动一个监控程序,将这个消息定时地循环写入到消息队列中,消息的内容可以是生成消息的时间戳,并且也会作为队列的消费者消费数据。业务处理程序消费到这个消息时直接丢弃掉,而监控程序在消费到这个消息时,就可以和这个消息的生成时间做比较,如果时间差达到某一个阈值就可以向我们报警。
想要减少消息的处理延迟,我们需要在消费端和消息队列两个层面来完成。
在消费端,我们的目标是提升消费者的消息处理能力,能做的是:
- 优化消费代码提升性能;
- 增加消费者的数量;
不过,第二种方式会受限于消息队列的实现。比如说,如果消息队列使用的是 Kafka 就无法通过增加消费者数量的方式,来提升消息处理能力。
因为在 Kafka 中,一个 Topic(话题) 可以配置多个 Partition(分区),数据会被平均或者按照生产者指定的方式,写入到多个分区中,那么在消费的时候,Kafka 约定一个分区只能被一个消费者消费,为什么要这么设计呢?其实是,如果有多个 consumer(消费者) 可以消费一个分区的数据,那么在操作这个消费进度的时候就需要加锁,可能会对性能有一定的影响。
所以说,Topic的分区数量决定了消费的并行度,增加多余的消费者也是没有用处的,那么我们可以通过增加分区来提高消费者的处理能力。
那么,如何在不增加分区的前提下提升消费能力呢?
既然不能增加 consumer,那么我们可以在一个 consumer 中提升处理消息的并行度,所以可以考虑使用多线程的方式来增加处理能力:我们可以预先创建一个或者多个线程池,在接收到消息之后,把消息丢到线程池中来异步地处理,这样,原本串行的消费消息的流程就变成了并行的消费,可以提高消息消费的吞吐量,在并行处理的前提下,我们就可以在一次和消息队列的交互中多拉取几条数据,然后分配给多个线程来处理。
另外,我们在消费队列中数据的时候还需要注意消费线程空转的问题。
总结我们了解了,如何提升消息队列的性能来降低消息消费的延迟,这里我们要你明确的重点是:
- 我们可以使用消息队列提供的工具,或者通过发送监控消息的方式,来监控消息的延迟情况;
- 横向扩展消费者是提升消费处理能力的重要方式;
- 选择高性能的数据存储方式,配合零拷贝技术,可以提升消息的消费性能。
其实,队列是一种常用的组件,只要涉及到队列,任务的堆积就是一个不可忽视的问题。