- 踩坑背景:目前的架构是mq消费失败会丢进补偿队列,补偿队列没有消费者,采用定时任务轮询去取补偿队列中的消息,while循环会一直取补偿队列中的消息,除非补偿队列为空时,才会终止循环。
如下图所示
- 线上故障状况:大量锁等待,锁超时,连接mq超时
分析代码后发现,
那…如果补偿队列有源源不断的大批量消息,那么会存在三个问题。
1、while循环一直不结束。
2、若消费补偿队列时失败,则会存放在errorList,若有大批量的消息失败,会导致有这个list会无限增大,最严重时甚至OOM
3、确认时采取了一次确认,若存在上百万上千万的补偿消息同时确认会导致占用时间增长,mq处理不过来,甚至阻塞,网络带宽被打满的情况
- 事后复现
当rabbitmq集群由5个节点组成的时候,如果2个或2个或以上节点在一定时间内有网络或连接阻塞问题,会导致集群出现不可恢复的脑裂问题。
事后进行了复现,在出现大量消息快速消费且批量ack时会出现sync节点信息同步情况,如果同步时间过长会导致同步失败以致于节点失联。
mq集群在满足以下特定条件后,出现卡死现象,不能正常生产和消费消息:
1.mq集群最大使用内存阈值设置超过60%
2.mq集群中内存中有大量消息,占用较多内存,接近设置阈值
3.mq集群处在频繁生产和消费消息的场景下,大块内存被快速交换使用
4.mq集群版本为3.5,较低,且运行在centos6系统
- 代码优化