MQ是message queue的缩写,本质上是个队列,FIFO先入先出原则,队列中存放的是message,是一种跨进程的通信机制,用于上下游传递信息。在互联网程序架构中,MQ是一种非常常见的上下游“逻辑解耦+物理解耦”的消息通信服务。使用了MQ以后,消息发送只需要依赖MQ,不用依赖于其他服务。
如果我们的订单系统最多能够处理掉一万次订单,这个处理能力应付正常时段的下单是搓搓有余了,但是如果在高峰期,比如淘宝的双11活动,有超过一万次的下单操作,系统则是处理不了的,需要做出相应的限制机制。那么如果我们使用消息队列作为缓冲,我们可以取消这个限制,将一秒内下的订单分散成一段时间来处理,这时有些用户可能在下单十几秒后才能收到下单成功的操作,但是比起限制下单的体验要好得多。
以电商为例,应用中由订单系统、库存系统、消息系统、支付系统等等,在用户创建订单以后,如果耦合的如上系统任何一个出现了故障,那么将导致下单功能异常。但是如果转变成消息队列的方式后,各个模块之间的依赖问题就会减少很多。比如如果下单的时候,消息系统出现了问题,需要一定的时间来修复,虽然消息系统出现了问题,但是其他模块是依旧可执行的,而消息系统需要发送的消息依旧存储在消息队列中,当消息系统修复好时,依旧可以成功发出对应的消息。
在传统模式中,订单系统调用支付系统,需要等待支付系统执行完毕后,返回执行结果,然后再进行支付系统的下一步操作,耦合度极高。但是使用消息队列,就可以解决这个问题,当订单系统调用支付系统后,支付系统开始执行,此时订单系统以后可以执行其他操作,当支付系统执行完毕后,会将返回结果放进消息队列中,再由消息队列转发给订单系统。
单机吞吐量万级,时效性ms级,可用性高,基于主从架构实现高可用性,消息可靠性较低的概率丢失数据。高吞吐量场景的使用较少。
为大数据而生的消息中间件,百万级TPS的吞吐量,再数据采集、传输、存储的过程中发挥着聚聚轻重的作用。单机写入TPS约在百万条/秒,最大的优点就是吞吐量高。时效性ms级,分布式,一个数据有多个副本,少数机器宕机不会丢失数据,不会导致不可用,消费者采用Pull的方式获取消息,消息有序。有Kafaka Web管理界面kafka-Manager。日志领域比较成熟,在大数据领域实时计算以及日志采集被大规模使用。
但是Kafka单机超过64个队列/分区,Load会发生明显的超高现象,队列越多,Load越高,发送消息的响应时间越长。使用短轮询的方式,实时性取决于短轮询的时间间隔,消费失败不支持重试。支持消费的顺序,但是一台代理宕机以后,就会产生消息乱序。
RocketMQ是出自阿里巴巴的开源产品,用JAVA语言实现,设计时参考的Kafka,并作出了一些改进。被阿里巴巴广泛应用在订单、交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。在阿里双11的活动中经历了多次考验,性能极佳。
单机吞吐量十万级,可用性高,分布式架构,消息可以做到0丢失,MQ功能较为完善,扩展性好,支持十亿级别的消息堆积,不会应为堆积导致性能下降。
于2007年发布,是一个在AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的消息中间件之一。
使用erlang语言实现,由于其语言的高并发特性,性能较好,吞吐量万级,MQ功能计较完善,稳定易用跨平台,支持多种语言。
RabbitMQ是一个消息中间件,它接收并转达消息。将消息存储在RabbitMQ中,等待需要的服务去其中取对应的消息。主要用于消息的接收、存储以及转发。
本文主要讲解RabbitMQ,它的安装在这里我们就不做过多介绍,网上一搜有很多教程。首先要下载erlang,配置好环境变量,然后下载RabbitMQ,配置好环境变量。配置完成后,启动sbin目录下的rabbitmq-server.bat,成功运行后,我们访问http://localhost:15672即可进入到管理界面。我们来看看它的管理界面:
产生数据时发送消息的角色。
一方面用来接收来自生产者的消息,另一方面它将消息推送到队列中。交换机必须确切地知道如何处理它接收地消息。是将消息丢弃还是推送到特定的队列,由交换机决定。
队列是RabbitMQ内部使用的一种数据结构,尽管消息流经RabbitMQ和应用程序,但是他们只能存储在队列中。生产者将消息发送到一个队列,消费者就可以尝试从一个队列中接收数据。
消费者是一个等待接收消息的程序。生产者消费者和消息中间件大多时候不在同一机器上,同一个应用程序可以是生产者也可以是消费者。
一、简单模式
二、工作模式
三、发布/订阅模式
四、路由模式
五、主题模式
六、发布/确认模式
接收和分发消息的应用,RabbitMQ Server就是Message Broker。
当多个不同的用户使用同一个RabbitMQ Server提供服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue等。类似于网络中的namespace概念。
publisher / consumer 和 broker之间的TCP连接。
如果我们每一次访问RabbitMQ都建立一个Connection,那么在消息大量建立TCP Connection的开销将是巨大的,效率也很低。Channel实在connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的channel进行通讯。channel有一个channel id,帮助客户端进和message broker识别channel,所以channel之间是完全隔离的。Channel作为轻量级的Connection极大减少了操作系统建立TCP connection的开销。
message到达broker的第一站,根据分发规则,匹配拆线呢表中的routing key,分发消息到queue中去。常见的交换机类型有:direct(point-to-point)直接交换机、topic(publish-subscribe)主题交换机、fanout(multicast)扇出交换机。
消息最终被推送到这里等待消费者取走消费。
exchange和queue之间的虚拟连接,binding中可以包含routing key,Binding信息被保存到exchange中的查询表中,用于message的分发数据。
死信就是无法被消费的消息,一般来讲生产者将消息投递到Broker中以后就直接到队列里去了,然后消费者再从队列中取消息。但是在某些应用的特殊业务场景下,一些特殊的原因导致了队列中的某些消息无法被消费,这样的消息如果我们没有对其进行处理,就变成了死信,进而形成了死心队列。
为了保证数据不丢失,需要我们使用RabbitMQ的死信队列机制,当消息发生异常时,将消息存入死信队列中,等后续能够消费的时候再将消息从队列中拿出来消费。像下单成功以后在指定的时间内没有付款时,自动失效。
死信的来源:
一、消息TTL(存活时间)过期
二、队列达到最大长度,队列已经满了,无法再添加数据到队列中。
三、消息被拒绝(basic.reject 或 basic.nack)并且requeue=false
延迟队列的内部是有序的,最重要的就是它的演示属性了,演示队列中的元素就是希望在指定的时间到了以后才开始对消息进行处理。简单来说,演示队列就是用来存放需要在指定时间被处理的元素的队列。比如说订单在十分钟内未支付自动取消订单,比如说用户注册成功以后三天内没有登录我们就进行短信提醒。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_51250453/article/details/121871152
内容来源于网络,如有侵权,请联系作者删除!