消息队列常见问题

总的来讲,消息队列常见问题要么消息不能多,要么不能少,还有顺序性,以及积压处理的问题等。

1.消息不能多

也就是说,消息不能重复消费,随之带来的幂等性问题。

解决:一般结合业务场景,有一个唯一key,比如通过主键,写的场景。通过校验主键是否存在的方式,来防止重复写,而且主键重复也会在数据库报错。

2.消息不能少

也就是说,消息丢失的问题。这里,我们先从消息队列的大致的架构上,我们了解到,大致分为生产者,MQ自身(broker),以及消费者。那么,分分三个角度来看这个问题

(1)生产者消息丢失

原因:在发送到broker过程中,可能因为网络故障的原因导致消息丢失。

解决:不同的组件解决方式可能不一样,但是大致思路是相似的。

就rabbitmq而言,有两种模式,事务模式和confirm模式都可以解决。首先事务模式,发送消息的时候开启事务,当有异常发生时,进行回滚事务并重新发送。但是这样搞得化势必会降低吞吐量和性能。再谈confirm模式,也就是当生产者写到MQ之后,MQ发送ok给生产者告知写成功,如果写入失败就回调一个nack接口。然后重新发送。

就kafka而言,设置ack=all,当所有的replica写入成功,才算做写入成功,如果没有成功,就无限重试。

就rocketmq而言。也是两种方式,一种是本地消息表+定时扫描,一种也是事务。第一种,一般是把异常的消息保存的消息表中,然后定时查看表中消息的状态,如果发送失败就重试。另一种事务,也就是发送消息之前开启半事务,然后发送失败时不执行事务。若发送成功,根据事务执行的结果判断提交还是回滚。

(2)MQ(broker)消息丢失

原因:在发送到mq之后,mq先载入到内存,这时宕机。或者kafka的leader切换follower过程中,partition的follower并没有把信息同步完成,这时候宕机。

解决:不同的组件解决方式可能不一样,但是大致思路是相似的。

就rabbitmq而言,开启持久化(创建queue时持久化以及发送消息时的deliveryMode设为2)。并结合前面的confirm模式,也就是当持久化成功后,再confirm,不然重试。

就kafka而言,一般是调整参数:topic的replication数大于1,kafka的replicas大于1,producer端ack设为all,retry设置为max。

就rocketmq而言,持久化到磁盘,默认策略时异步刷盘,改为同步刷盘。但是这样也会造成吞吐量下降,所以还需结合具体业务场景。

(3)消费端消息丢失

原因:消费端获得消息后,并没来得及处理,这是发生宕机。那么mq会以为已经处理过,那么这条消息就会丢失。

解决:不同的组件解决方式可能不一样,但是大致思路是相似的。

就rabbitmq而言,关闭自动ack,使用手动提交。

就kafka而言,关闭自动ack,使用手动提交。

就rocketmq而言,默认就是手动提交,一般不会丢失。

3.顺序性问题

一般读写操作都要注意。

解决:大致思路就是,在发送消息的时候,可以根据相同的key,比如说业务主键,来确定这条消息打入到同一个queue中,然后这个queue也指定一个consumer来消费。这个consumer中可以内部开启多个线程,一个线程对应消费一个内存queue。

相关推荐
懒洋洋的华3696 小时前
消息队列-Kafka(概念篇)
分布式·中间件·kafka
happycao1231 天前
kafka 一步步探究消费者组与分区分配策略
中间件·kafka
问道飞鱼2 天前
分布式中间件-redis相关概念介绍
redis·分布式·中间件
苹果酱05672 天前
使用 React Testing Library 测试自定义 React Hooks
java·开发语言·spring boot·后端·中间件
没有名字的小羊2 天前
fastjson漏洞
运维·网络·web安全·中间件
竹等寒2 天前
中间件常见漏洞
android·web安全·网络安全·中间件
problc2 天前
零拷贝技术在现代编程语言和中间件中的应用
中间件
傻傻虎虎2 天前
【系统架构设计】基于中间件的开发
中间件·系统架构
老K(郭云开)2 天前
汉王手写签批控件如何在谷歌、火狐、Edge等浏览器使用
前端·chrome·中间件·edge·创业创新·html5
Thuni_soft3 天前
华宇TAS应用中间件斩获2024鲲鹏应用创新大赛北京赛区总决赛二等奖!
中间件