Rabbitmq定义:
rabbitmq是采用AMQP高级消息队列协议的一种消息队列技术,并且在消费的时候,不需要确保提供方的存在,实现了服务之间的高度解藕
优点:
1.在分布式系统下具备异步、削峰、负载均衡等一系列功能
2.实现了消费者和生产者之间的解藕
3.拥有持久化机制,消息,队列中的信息可以保存下来
4.对于高并发场景下,利用消息队列可以使得同步访问变为串行访问,达到了一定量的限流,利于数据库的操作
5.可以使用消息队列达到异步下单的效果,排队中,后台进行逻辑下单
缺点:
1.系统的可用性降低
2.系统引入的外部依赖越多,越容易挂掉,这样会使系统的复杂度提高
3.会出现一致性问题
Rabbitmq使用场景:
1.服务之间的通信 2.顺序消费 3.定时任务 4.请求削峰
如何确保消息正确的发送到Rabbitmq?并且确保消息接收方消费了消息?
发送方确认模式
将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID,一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一ID),如果Rabbitmq发生内部错误从而导致消息丢失,会发送一条nack(not acknowledged)未确认消息
发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息,当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息
接收方确认机制
接收方接收的每一条消息后都必须进行确认(消息接收和消息确认是两个不同的操作)。只有消费者确认了消息,Rabbitmq才能安全的把消息从队列中删除。这里没有用到超时机制,Rabbitmq仅通过Consumer的连接中断来确认是否需要重新发送消息,也就是说,只要连接不中断,Rabbitmq给Consumer足够长的时间来处理消息,保证数据的一致性
特殊情况下:
如果是消费者接收到消息,在确认之前断开了连接或者是取消订阅,Rabbitmq会认为消息没有被分发,然后重新分发给下一个订阅的消费者(这里可能会存在消息重复消费的隐患,要去重)
如果消费者接收到消息却没有确认消息,连接也未断开,则Rabbitmq认为会该消费者繁忙,将不会给该消费者分发更多的消息
Rabbitmq如何避免消息重复投递或者是重复消费?
在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,作为去重的依据(消息投递失败并重传),避免重复的消息进入队列
在消息消费时,要求消息题必须要有一个bizid(对于同一业务全局唯一,如支付ID,订单ID,帖子ID等)作为去重依据,避免同一条消息被重复消费
Rabbitmq消息基于什么传输?
由于TCP连接的创建和销毁开销比较大,且并发数受系统资源的限制,会造成性能瓶颈,Rabbitmq使用信道的方式来传输数据,信道是建立在真实的TCP连接内的虚拟连接,且每条TCP连接上的信道数量没有限制
Rabbitmq如何确保消息不丢失
消息持久化,前提是队列必须持久化。Rabbitmq确保持久性的消息能从服务器重启中恢复的方式是,将他们写入磁盘上的一个持久化日志文件,当发布一条持久化消息到持久交换器上,Rabbitmq会在消息提交到日志文件后才发送响应
一旦消费者从持久化队列中消费了一条持久化消息,Rabbitmq会在持久化日志中把这条消息标记为等待垃圾收集
如果持久化消息在被消费之前Rabbitmq重启,那么Rabbitmq会自动重建交换器和队列(以及绑定),并重新发布持久化日志文件中的消息到合适的队列
Rabbitmq如何保证消息顺序性?
设置每一个消费者对应一个queue,把需要保证顺序的数据,放到一个queue中,这样数据就会被一次消费到
Rabbitmq可能导致消息丢失的场景
1.生产者写消息的过程中,网络传输错误,导致消息丢失
解决方案:MQ是支持事务,channel.txSelect()选择事务,channel.txCommit()提交事务
2.接收到消息暂存在内存中,还没来得及消费,MQ挂掉了,就导致数据丢失
解决方案:设置queue持久化机制,持久化queue的元数据,但是不会持久化queue里面的数据,发送消息的时候,将消息deliveryMode设置为2,就是将消息持久化
3.消费者消费到这个消息之后,还没来得及处理,自己就挂掉了,但是MQ以为已经处理完了这条消息
解决方案:设置channel.confirm机制,异步处理保证消息不丢失,一般来说在代码中是ack和nack两种消费者端,将autoAck关掉,手动确认消息消费完成提交ack
Rabbitmq消息队列的演示以及过期失效的问题
场景:消费端因为故障或者是性能瓶颈,导致消费消息很慢,MQ中有大量的消息堆积
线上临时处理办法:消费端修改一下代码,每次消费之后数据不是进去到数据库中,而是在新建一个topic,里面有很多歌partition,同时对应很多个消费者,加速消费
解决方案:消息不要设置过期时间,如果是有订单消息丢失,手动重新发送MQ,消费者端快速消费掉消息,等晚上时间空余了之后再重新消费