RabbitMQ学习总结

RabbitMQ学习总结

学习了消息队列中间件RabbitMQ,在这里做一些学习总计。

什么是RabbitMQ?

采用AMQP高级消息队列协议的一种消息队列技术,最大的特点就是消费并不需要确保提供方存在,实现了服务之间的高度解耦

RabbitMQ作用?

1、可以实现生产者与消费者之间的解耦
2、在高并发场景下,可以实现削峰限流的作用,防止突然大量访问到数据库导致宕机,
3、可以使用消息队列达到异步下单的效果,排队中,后台进行逻辑下单

RabbitMQ工作机制:

生产者、消费者和代理 在了解消息通讯之前首先要了解3个概念:生产者、消费者和代理。 生产者:消息的创建者,负责创建和推送数据到消息服务器;
消费者:消息的接收方,用于处理数据和确认消息;
代理:就是RabbitMQ本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。

  • 基于什么传输?
    基于TCP连接的虚拟链接(信道)来传输,一个TCP可以有多个信道,可以提高系统处理连接的能力,减少TCP建立连接和断开连接带来的消耗
  • 消息如何分发?

若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息只会分发给一个订阅的消费者(前提是消费者能够正常处理消息并进行确认)。
通过路由可实现多消费的功能

  • 消息如何路由?

消息提供方->路由->一至多个队列 消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。
通过队列路由键,可以把队列绑定到交换器上。
消息到达交换器后,RabbitMQ会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则);
常用的交换器主要分为一下三种:
fanout:如果交换器收到消息,将会广播到所有绑定的队列上
direct:如果路由键完全匹配,消息就被投递到相应的队列
topic:可以使来自不同源头的消息能够到达同一个队列。使用topic交换器时,可以使用通配符

如何确保消息不丢失不重复?

  • 确认机制和持久化
    1、生产者数据丢失
    2、消息队列数据丢失(持久化、集群)
    3、消费者数据丢失(自带ACK、手动ACK)

发送方确认模式:
将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID。
一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一ID)。
如果RabbitMQ发生内部错误从而导致消息丢失,会发送一条nack(not acknowledged,未确认)消息。
发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。
接收方确认机制
接收方消息确认机制:消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ才能安全地把消息从队列中删除。
这里并没有用到超时机制,RabbitMQ仅通过Consumer的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ给了Consumer足够长的时间来处理消息。保证数据的最终一致性;
下面罗列几种特殊情况:
如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要去重)
如果消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,将不会给该消费者分发更多的消息。

  • 防止重复消费

1、在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,作为去重的依据(消息投递失败并重传),避免重复的消息进入队列;
2、在消息消费时,要求消息体中必须要有一个bizId(对于同一业务全局唯一,如支付ID、订单ID、帖子ID等)作为去重的依据,避免同一条消息被重复消费。

如何保证消息不被重复消费? 保证消息不被重复消费的关键是保证消息队列的幂等性,这个问题针对业务场景来答分以下几点:
1.比如,你拿到这个消息做数据库的insert操作。那就容易了,给这个消息做一个唯一主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。
2.再比如,你拿到这个消息做redis的set的操作,那就容易了,不用解决,因为你无论set几次结果都是一样的,set操作本来就算幂等操作。
3.如果上面两种情况还不行,上大招。准备一个第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将以K-V形式写入redis。那消费者开始消费前,先去redis中查询有没消费记录即可。

比如在设计秒杀系统中引用了消息队列中间件,为了防止消息被重复消费问题,可以在库存表更新库存的是时候多一个判断库存大于0机制(有行锁,可以防止并发问题),以及在明细表中建立唯一索引,防止重复下单问题。

常用三种交换器

参考链接:https://blog.csdn.net/xu768840497/article/details/81605149

缺点

使用了消息队列会有什么缺点?
1.系统可用性降低:你想啊,本来其他系统只要运行好好的,那你的系统就是正常的。现在你非要加个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性降低
2.系统复杂性增加:要多考虑很多方面的问题,比如一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。因此,需要考虑的东西更多,系统复杂性增大。

总结
在使用消息队列时,要注意消息丢失以及重复消费的问题:
消息丢失问题:1、消费者宕机,2、消息队列自身宕机
重复消费问题:1、防止重复消息入队,2、防止在消费者处重复消费

参考文献:https://juejin.im/post/5be04f336fb9a049e5531455
https://juejin.im/post/5b3f5119e51d45190e34d47a

你可能感兴趣的:(中间件,优化)