📝作者简介:
大家好,我是CBeann,CSDN博客专家,阿里云专家博主。
22届校招进入阿里广告部门从事Java开发工程师。
平时有空会帮大家解决问题,模式面试和日常答疑,并且提供免费云服务器使用。
有一起卷的可以加我的微信:CHAI956056312,大家一起学习,一起进步。
项目场景
广告包括图片、URL和文字等信息。这些信息构成的广告不是随便投放的,要审核,而审核是风控部门审核,简单的交互逻辑如下。
对于从RocketMQ到广告系统的这条链路来说,又放大到下面的这张图。其中拉取消息中间件AMB做消费的监控和限流。
问题描述
这个是从一个工单反馈发现的,这个问题表象描述为先发的消息后消费到。正常是风控机审先返回结果,然后风控人审后返回结果。这次出现了机审(审核通过)竟然覆盖了人审(审核拒绝)的结果,最后广告被错误的投放出去了。
消息顺序乱序,很明显就是上游没做分桶,没有保证相同的ID路由到同一个MQ的队列上,但是仔细想一想,这种常识性问题理论上是不会犯的,而且出问题早就出了,原因只可能出现从MQ到consumer这条链路上,即下图。
查了拉取消息中间件AMB的这个配置,发现没有配置顺序消费,即从MQ上拉取到消息然后多线程消费,自然就会出现上面的这种先发消息后消费的情况,信心满满的感觉把这个bug修复了。
but出现消费堆积了。。。
问题分析
还是先看一下下面的这张图
其中中间的AMB任务配置的是32*32。
即32个拉线程,每个拉线程下挂着32个消费线程。
修改为顺序消费配置后,消费出现了堆积。
首先下游的HSF接口(HTTP)接口是没有改的,所以下游消费能力不变。
32个拉取线程还是32个,说明拉取MQ消息量还是不变的。
顺序消费改变了什么呢?
改变的是拉取线程拿到消息后对QueueId做hash然后路由到拉取线程下的哪个消费线程。
之前同一个拉取线程拉到不同的队列会被分配到不同的消费线程。
现在同一个拉取线程拉到不同的队列会根据QueueId的HASH到不同的消费线程,此时可能HASH值相同,那么此时就会让一个消费线程消费,消费速录就变为原来的二倍。
解决方案:
只有保证多个队列的QueueId做hash不路由到一个消费线程上,理论上就能解决问题。
方案1—修改路由算法:在拉取线程和消费线程中间改路由算法,操作成本极高。
方案2—HASH上移:扩大拉取线程,扩大到和队列数相同,然后每一个拉取线程下配置1个消费线程(配置多了浪费),这样其实就可以保证不同的队列消息进入不同的消费线程,因为拉取线程就已经不同了。
总结
定位到是哪个地方有问题,然后去解决和优化。
有的场景不能扩大MQ队列数解决消费堆积。
核心就是提高下游的消费能力,使得下游疯狂消费。