rabbitmq2-这可能是最全的rabbitmq概览了

在学习一个技术的时候,首先想到的应该是应用场景,然后在对比技术和技术选型的时候应该结合自己的业务,再结合每一个技术的特点进行技术的选择,这篇博文就详细的描述一下rabbitmq的特性

一、rabbitmq的总体模型图

image.png

1、一些名词解释:
  • 生产者(P):提供消息的一方的称谓
  • 消费者(C):接受消息的一方的称谓
  • 队列(Q):存储消息的一种数据结构
  • exchange (交换机|路由器):提供P到Q之间的匹配
  • routing key:当前的消息将会被路由到那个Q中
  • binding key:联系Exchange和Q,Binding Key由Consumer在Binding Exchange与Message Queue时指定,而Routing Key由Producer发送Message时指定,两者的匹配方式由Exchange Type决定。
  • Connection:tcp连接
  • Channel:复用tcp连接的通道(埋下一个知识点,我们一会会继续
    聊)
  • ExchangeType
    • direct :默认的模式,当routing key和binding key完全匹配的时候,才可以获取消息
    • topic:与上面的模式相同,但是routing key可以和binding key进行模糊匹配
    • header:忽略ExchangeType,header本来就是键值对结构,依据header属性进行匹配
    • fanout:和上面一样忽略ExchangeType的设置,把消息广播到它所知道的所有的队列
2、聊聊设计思想:
  • Connection:
    看到这个东西你是不是想到了数据库Connection,其实它们的本质都是tcp连接,你是否还想到了数据库连接池(c3p0、druid……),其实用在这里都是一样的效果,有兴趣你可以看看spring在整合rabbitmq的时候是如何来写的只需要debug进去即可
  • Channel:对于一个连接来说想要保持资源的隔离和快速的通过exchange匹配到queue,这个机制是非常棒的,这么优秀的设计思想,的确是值得我们去学习的,其实把这个点想通,然后套在多线程里面也是通用的。

二、rabbitmq如何确保消息的可靠性

这个点是我在群里面经常被问到的问题,很多博客也差不多是复制文档上面的下来,今天希望我能把这个问题给讲解清楚。话还是回到前面当初是怎么想到学习这个技术的呢??

1、生产者端的可靠性的保障
1.1 事务机制

image.png
是不是基本和jdbc的一致。事务的机制保障的是消息能够投递出去,

1.2 confirm机制的保障:

相比于事务机制,confirm的性能要提高200倍,confirm和事务机制是互斥的,即不能同时使用
rabbitmq提供下列几个方法来实现:
开启channel.confirmSelect()
①同步普通模式(阻塞)waitForConfirms(),发送一条等待服务端confirm后在发送第二条,这实际上一种串行的模式效率不高
②同步批量模式:每发送一批消息之后,调用waitForConfirms()方法,等待服务端confirm,但假如一旦出现confirm返回false的话,那么客户端要将这批消息重发会带来重复消息
③异步监听模式:confirmListener

2、消费者的保障

消费者端的消息重试机制:
①:当消费者端挂掉了即当前的channel断开了连接,那么消息会自动重回队列,重新分发给下一个消费者
②:当前消费者拒收这个消息,那么rabbitmq提供参数可以使得此消息重回队列,那么此条消息便可以继续分发给下一个消费者处理,确保这个消息一定会有消费者去处理
以上的两个机制便确保了消息只要发出一定会被消费,下面我们在说如何利用这一机制来实现分布式事务。

问题: 当消费者消费完消息,发送应答的时候挂掉了会出现什么情况?

这种情况会造成消息的重复消费,A已经消费了消息,但是应答发送的时候网络中断,这个时候channel已经断开了,就需要重如队列,下一个消费者B就会继续消费这个消息,就会造成消息的重复消息,所以在消费者端一定要有一个状态表保存消息的状态,防止被重复消费。

3、服务器端的保障:

①:提供持久化模式,开启这种模式即使服务器宕机,也能在重启的情况下保证消息的不丢失
②:提供集群的方式

三、rabbitmq的几种工作模式和应用场景:

1、简单模式:
image.png
一个生产者一个消费者一个队列非常简单的结构,基本上这个结构没有什么用
2、work模式:
image.png
一个生产一个队列,多个消费者,每个消费者获取的消息唯一
3、订阅模式:
image.png
Exchange将会把消息投递到所有它已知的Q,然后连接Q 的所有的C都能获取到消息。此时ExchangeType的模式为fanout
4、路由模式:
image.png
由routing key决定把消息往哪个队列里面投递,有binding 匹配routing key的结果来决定C是否可以获取此Q中的消息,这种模式下ExchangeType必须为direct
5、统配符模式:
image.png
在这种模式下可以模糊匹配

2、应用场景:

1、简单模式:这种模式几乎没有什么应用场景
2、work模式:这种应用的也比较少
3、发布订阅模式:这种模式适用于通知,例如通知所有的商户周五晚上服务器更新
4、路由模式:在集群的环境下,我们会将一个系统的所有消息都交由这个集群来处理,所以所有的消息必须要归类,那么这个模式就在这种情况下可以高效的处理消息
5、统配符模式:基本和上面的类似,可以接受一类的消息

四、消息的公平分发:

场景:现在有两个消费者,A的吞吐量为10,B的吞吐量为5。
在默认的模式下面,消息队列不管消费者是否处理完毕,都会继续下发下一条消息,造成的结果就是A 获取10条消息,B也获取10条消息,显然这样会拖慢整体的处理速度,本着能者多劳的原则。我们会尽量的让A、B都能有一个合理的负荷来提高系统的整理的处理速度

channel.basicQos(int prefetchCount);

这个语句就会使得一次性下发prefetchCount个消息,等待处理完成后在下发同样的数量的消息,这样会提升系统的整体的吞吐量。

五、再聊分布式事务

在分布式的场景中,已经无法在做到ACID了,这个时候我们追求最终的一致性,那么现在实现最终一致性的方法还没有成熟的方案,据说阿里搞了一个GTS但是目前还没有开源。本篇在这个大环境下肯定是将使用rabbitmq来实现分布式事务的最终一致性 。
- 消息的可靠性,rabbitmq借助于生产者端的确认机制、消费者的重试机制、服务器端的持久化机制及集群机制,可以确保消息不丢失,只要消息发送出去就一定会被消费,如果出现大量的消息堆积,那这个时候就可以考虑在架设缓存或者增加节点了
- 消息延迟是目前mq中最低的以微妙来计
- 借助于消费者端的事务状态表来保证消息的重复消费

目前就聊到这里,实践出真知,下面的系列文章将会进入实战环节。

猜你喜欢

转载自blog.csdn.net/weixin_42849915/article/details/82114357
今日推荐