文章目录
RabbitMQ是目前非常热门的一款消息中间件,凭借其高可靠、易扩展、高可用及丰富的功能特性受到越来越多公司的青睐。
什么是消息中间件
消息(Message)是指在应用间传送的数据。消息可以非常简单,比如只包含文本字符串、 JSON 等,也可以很复杂,比如内嵌对象。
消息队列中间件,也可以称为消息队列或者消息中间件。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。
它一般有两种传递模式:点对点(P2P,Point-to-Point)模式和发布/订阅(Pub/Sub)模式。
点对点模式
点对点模式是基于队列的,消息生产者发送消息到队列,消息消费者从队列中接收消息,队列的存在使得消息的异步传输成为可能。
发布订阅模式
发布订阅模式定义了如何向一个内容节点发布和订阅消息,这个内容节点称为主题(topic),主题可以认为是消息传递的中介,消息发布者将消息发布到某个主题,
而消息订阅者则从主题中订阅消息。主题使得消息的订阅者与消息的发布者互相保持独立,不需要进行接触即可保证消息的传递,发布/订阅模式在消息的一对多
广播时采用。
目前开源的消息中间件有很多,比较主流的有RabbitMQ、Kafka、ActiveMQ、RocketMQ等。
消息中间件的作用
解耦
场景说明:
用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。
传统模式的缺点:
假如库存系统无法访问,则订单减库存将失败,从而导致订单失败订单系统与库存系统耦合。
引入消息队列:
订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功
库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作
优点:
实现订单系统与库存系统的应用解耦。
假如在下单时库存系统不能正常使用,那也不会影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。
为了保证库存肯定有,可以将队列大小设置成库存数量,或者采用其他方式解决。
异步通信
场景说明:
用户注册后,需要发注册邮件和注册短信。传统的做法有两种串行的方式;并行方式。
**(1) 串行方式:**将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。
**(2) 并行方式:**将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提
高处理的效率。
引入消息队列:
将注册信息写入数据库成功后,将消息分别写入短信队列和邮件队列,然后返回客户端。
同时短信和邮件队列对应的消费者,消费队列中的消息,给对应的用户发送短信或者邮件。
优点:
将不是必须的业务逻辑,放到消息队列中异步处理,提高系统吞吐效率。
流量削峰
应用场景:
系统其他时间A系统每秒请求量就100个,系统可以稳定运行。系统每天晚间八点有秒杀活动,每秒并发请求量增至1万条,但是系统最大的处理能力只能每秒处理1000个请求,于是系统崩溃,服务器宕机。
之前架构:
大量用户(100万用户)通过浏览器在晚上八点高峰期同时参与秒杀活动。大量的请求涌入我们的系统中,高峰期达到每秒钟5000个请求,大量的请求打到MySQL上,每秒钟预计执行3000条SQL。但是一般的MySQL每秒钟扛住2000个请求就不错了,如果达到3000个请求的话可能MySQL直接就瘫痪了,从而系统无法被使用。但是高峰期过了之后,就成了低峰期,可能也就1万用户访问系统,每秒的请求数量也就50个左右,整个系统几乎没有任何压力。
**引入MQ:**100万用户在高峰期的时候,每秒请求有5000个请求左右,将这5000请求写入MQ里面,系统A每秒最多只能处理2000请求,因为MySQL每秒只能处理2000个请求。系统A从MQ中慢慢拉取请求,每秒就拉取2000个请求,不要超过自己每秒能处理的请求数量即可。MQ,每秒5000个请求进来,结果只有2000个请求出去,所以在秒杀期间(将近一小时)可能会有几十万或者几百万的请求积压在MQ中。
关于流量削峰:秒杀系统流量削峰这事儿应该怎么做?
这个短暂的高峰期积压是没问题的,因为高峰期过了之后,每秒就只有50个请求进入MQ了,但是系统还是按照每秒2000个请求的速度在处理,所以说,只要高峰期一过,系统就会快速将积压的消息消费掉。我们在此计算一下,每秒在MQ积压3000条消息,1分钟会积压18万,1小时积压1000万条消息,高峰期过后,1个多小时就可以将积压的1000万消息消费掉。
注意:中间件的在不同的应用场景可能会有不同的作用,具体看怎么应用,并不局限于上述场景。
引入消息队列的优缺点
优点
优点就是以上的那些场景应用,就是在特殊场景下有其对应的好处,解耦、异步、削峰。
缺点
系统的可用性降低:系统引入的外部依赖越多,系统越容易挂掉,本来只是A系统调用BCD三个系统接口就好,ABCD四个系统不报错整个系统会正常运行。引入了MQ之后,虽然ABCD系统没出错,但MQ挂了以后,整个系统也会崩溃。
系统的复杂性提高:引入了MQ之后,需要考虑的问题也变得多了,如何保证消息没有重复消费?如何保证消息不丢失?怎么保证消息传递的顺序?
一致性问题:A系统发送完消息直接返回成功,但是BCD系统之中若有系统写库失败,则会产生数据不一致的问题。
总结
所以总结来说,消息队列是一种十分复杂的架构,引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避。引入MQ系统复杂度提升了一个数量级,但是在有些场景下,就是复杂十倍百倍,还是需要使用MQ。
RabbitMQ
RabbitMQ 是一个开源的遵循AMQP
协议实现的基于 Erlang 语言编写,支持多种客户端(语言),用于在分布式系统中存储消息,转发消息等。
RabbitMQ 的特点
可靠性
RabbitMQ提供了多种技术可以让你在性能和可靠性之间进行权衡。这些技术包括持久性、投递确认、发布者证实和高可用性。
灵活的路由
消息在到达队列前是通过交换机进行路由的。RabbitMQ为典型的路由逻辑提供了多种内置交换机类型。如果你有更复杂的路由需求,可以将这些交换机组合起来使用,甚至你可以写自己的交换机类型,并且当做RabbitMQ的插件来使用。
集群
在相同局域网中的多个RabbitMQ服务器可以被聚合在一起,作为一个独立的逻辑代理来使用。
联合
对于服务器来说,它比集群需要更多的松散和非可靠链接。为此RabbitMQ提供了联合模型。
高可用的队列
在同一个集群中,队列可以被镜像到多个机器中,以确保当其中某些硬件出现事故后,你的消息仍然是安全的。
多协议
RabbitMQ 支持多种消息协议中的消息传递。
广泛的客户端
只要是你能想到的语言几乎都有与其相适配的RabbitMQ客户端。
可视化管理工具
RabbitMQ附带了一个易于使用的可视化管理工具,它可以帮助你监控消息代理的每一个环节。
追踪
如果你的消息系统有异常行为,RabbitMQ还提供了追踪的支持,让你能够发现问题所在。
插件系统
RabbitMQ附带了各种各样的插件来对自己进行扩展。甚至你也可以写自己的插件来使用。