Rabbitmq消息队列的问题

本文深入探讨了消息队列的基本概念,如如何防止消息重复消费、消息队列的优点和缺点、应用场景,以及死信队列和延时队列的工作原理。此外,还详细介绍了RabbitMQ的事物消息机制、交换机类型、持久化机制,并讨论了如何保证消息的可靠性传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、如何保证消息不会给重复消费

幂等:一个数据或一个请求,重复来多次,确保对应的数据是不会改变的,不能出错。

  • 如果写redis,就没问题,反正每次都是set,天然的幂等性
  • 生产者发送消息的时候带上全局唯一的id,消费者拿到消息后,先根据这个id去redis中查找,之前没有消费过的话就处理,并且写入这个id到redis中。如果消费过了,则不处理
  • 基于数据库的唯一键

2、消息队列的优缺点,使用场景

优点

  1. 解耦,降低系统之间的依赖
  2. 异步处理,不需要等待
  3. 削峰填谷,将流量从高峰期引导低谷期进行处理

缺点:

  1. 增加了系统的复杂型,幂等,重复消费,消息丢失等问题。
  2. 系统可用性降低,mq的故障会影响系统可用
  3. 一致性,消费端可能失败

场景:日志采集,发布订阅

3、死信队列是什么?延时队列是什么?

  1. 死信队列也是一个消息队列,它是用来存放那些没有成功消费的消息,通常可以用来处理作为消息重试
  2. 延时队列是用来存放需要在指定时间被处理的元素的队列,通常用来处理一些具有过期性操作的业务,比如十分钟内未支付就取消订单。

4、RabbitMQ事物消息机制

通过对信道设置实现

  1. channel.txSelect():通知服务器开启是事务模式;服务端会返回TX.select-OK
  2. channel.basicPublish:发送消息,可以是多条消息,可以是消费消息提交ack
  3. channel.txCommit:提交事务
  4. channel.txRollback:回滚事务

消费者使用事物:

  1. autoAck=false,手动提交ack,以事物提交或回滚为准
  2. autoAck=true,不支持事务,也就是说你即使在收到消息之后再回滚事务也于事无补,队列已经把消息一起移除了

如果其中任意一个环节出了问题,就会抛出IOException异常,用户可以拦截异常进行回滚事务,或决定要不要重复消息。事务消息会降低rabbit的性能。

5、RabbimqMq的交换机类型

  • fanout:扇形交换机,不再判断routekey,直接将消息分发给所绑定的队列(发布订阅)
  • direct:判断routekey的规则是完全匹配的模式,即发送消息指定的routekey要等于绑定的routekey
  • topic:判断routekey的规则是模糊匹配的
  • header:绑定队列与交换机的时候指定一个键值对,当交换机在分发消息的时候会先解开消息体里的headers数据,然后判断里面时候有设置的键值对,如果发现匹配成功,才将消息分发到队列中;这种交换机类型在性能上交差,在实际工作中很少用到。

6、RabbitMq的持久化机制

  1. 交换机持久化:exchange_declare创建交换机时通过参数绑定
  2. 队列持久化:queue_declare创建队列时通过参数绑定
  3. 消息持久化:new AMQPMessage创建消息时通过参数绑定

append的方式写文件,会根据大小自动消息生成新的文件,rabbitmq启动时会创建两个进程,一个负责持久化消息的存储,另一个负责非持久化的存储(内存不够时)

消息存储的时候在ets表中记录消息在文件中的映射以及消息信息(包括id,偏移量,有效数据,左边文件,右边文件),消息读取时根据该信息在文件读取,同时更新信息

消息删除智慧虫ets删除,变为垃圾数据,当垃圾数据超出比例(默认50%),并且文件数达到了3个,触发垃圾回收,锁定左右两个文件,整理左边文件有效数据,将右边文件有效数据写入左边,更新文件信息,删除左边,完成合并。当一个文件的有用数据等于0时,删除该文件

写入文件钱先写入buffer缓冲区,如果buffer已满,则写入文件(此时只是操作系统的页存)
每隔25ms刷新一次磁盘,不管buffer满没满,都会将buffer和页存中的数据落盘
每次消息写入后,如果没有后续写入请求,则直接刷盘

7、Rabbitmq如何保证消息的可靠性传输

1、使用事物消息
2、使用消息确认机制

发送方确认:

  1. channel设置为comfirm模式,则每条消息会被分配一个唯一id
  2. 消息投递成功,信道会发送ack给生产者,包含了id,回调了comfirmCallback接口
  3. 如果发送错误导致消息丢失,发送nack给生产者,回调ReturnCallback接口
  4. ack和nack只要一次触发,且只有一次,异步触发。可以技术发送消息。

接收方确认:

  1. 声明队列时,指定noack=false,broker会等待消费者手动返回ack,才会删除消息,否则立刻删除
  2. booker的ack没有超时机制,只会判断链接是否断开,如果断开,消息会被重写发送

8、rabbitmq的死信队列,延迟队列的原理

死信队列:

  1. 消息被消费方否定确认,使用了channle.basicNackchannel.basicReject,并且此时requeue属性被设置了false
  2. 消息在队列中存活时间超过了设置的TTL时间
  3. 消息队列的数量已经超过了最大队列长度

那么该消息成为死信队列。如果配置了死信队列信息,那么该消息会被丢进死信队列中,如果没有配置,则该消息将会被丢弃

为每个需要死信业务队列配置一个死信交换机,同一个项目的死信交换机可以共用一个,然后为每个业务队列分配一个单独的routekey,死信队列只不过是绑定在死信交换机上的队列,死信交换机也不是什么特殊的交换机,只不过是用来接受死信队列,那么可以为任何类型的交换机

TTL:一个消息或改队列中所有消息的最大存活时间
如果一个消息设置了TTL属性或者进入了设置TTL属性的队列中,那么这条消息在TTL设置的时间内没有被消费,则会成为“死信”。如果同时配置了队列的TTL和消息的TTL,那么较小的那个值将会被使用

只需要消费者一直消费私信队列里面的消息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值