项目中用到了消息队列,但是自己还只是大概了解,于是打算系统的学习一下。学东西一定要注意体会思想,理解了思想就是学一通百,不注意理解思想,很容易就会淹没在技术的海洋中。

MQ与JMS

java是一个喜欢发布标准,让别人实现的语言,这个标准你可以理解为接口,像JDBC就是一组接口,由不同的数据库厂商负责实现,这是一个相当成功的设计。JMS也是类似于JDBC这样的标准,但是并没有做到像JDBC这么成功,所有的消息服务都按JMS来。

曾经的我以为MQ和JMS的关系是这样的:

像是接口和实现类一样,

但是实际上: 只有ActiveMQ完全遵守了JMS协议。RocketMQ、RabbitMQ、KafkaMq并不怎么遵守JMS。

JMS是什么?

The Java Message Service (JMS) API is a messaging standard that allows application components based on the Java Platform Enterprise Edition (Java EE) to create, send, receive, and read messages. It enables distributed communication that is loosely coupled, reliable, and asynchronous.

java 消息服务接口是一个基于java平台创建、发送、接收消息的标准,在分布式系统中常常被用来解耦合,异步发送消息。

MQ = message queue

message queue 消息队列,首先是队列,队列是一种数据结构,一般情况是先进先出。

那我们一般用消息队列来做什么呢? 或者消息队列可以用来做什么呢 ?

可以用来做中间件

那什么是中间件? 查了一些资料,发现并没有严格的定义,目前较为接受的定义是将具体业务和底层逻辑解耦的组件。
我们姑且可以将其理解为中介,我们想要租房的话,通常不会自己去找房东,通常也比较难找,也比较麻烦。如果你真的不想让中介占到一点便宜,跟某块地区的房东已经建立了战略合作关系,于是你每换一个地方就要自己再找一下房东,你于这个地区就产生了严重的耦合,房东也与你产生了耦合。

通常情况下,房东会将自己的房子委托给中介或者托管在某个平台,租房子的人通过中介或者托管平台来看房子。这个中介和被托管的平台我们就可以理解为中间件。有效的实现了房东和访客解耦,房东和租房子的人通过中介或托管平台交流。

所以你可以看到Redis也可以算进中间件,Redis也可以做消息队列。

实际的应用场景中,MQ被当做中间件时往往用于两个系统间进行通信,

A系统将B系统需要的消息放入消息队列中,B系统从消息队列中获取。

有人可能会问了,为什么B系统不直接调用A系统的接口呢? 要放一个消息队列呢?
其实也不是不行,那这样就耦合在一起了,也就是说A跟着动,B也要跟着动,软件行业普遍厌恶改动。
如果是在分布式系统中,我们就更希望调用关系清晰一点了,两个系统在某种意义上像是两个国家,两个国家之间的交流是通过外交部,而两个系统之间的交流就是通过消息队列。

削峰填谷

消息队列的另一个应用场景就是秒杀,秒杀情况下,一段时间内请求会很多,系统会承受不住这么多请求,请求也可以算做消息。

就能够让系统本身处理的请求量,保持在一个平稳的水平。

异步消息

事实上这根中间件有些重合,也可以算到解耦合的一部分。
RocketMQ的官方文档在介绍的作用或使用长江时,第一个讲的就是异步解耦。
作为淘宝/天猫主站最核心的交易系统,每笔交易订单数据的产生会引起几百个下游业务系统的关注,包括物流、购物车、积分、阿里妈妈、流计算分析等等,整体业务系统庞大而且复杂,架构设计稍有不合理,将直接影响主站业务的连续性。
一个订单算作一个消息,会被多个系统使用,像极了生产者、消费者模型。作为生产订单的这一方,并不直接和消费订单的这一方产生直接联系。

主流的MQ产品

  • RocketMQ
阿里巴巴出品,现在交给apache开源基金会维护。并不完全遵守JMS协议,支持的协议也比较多,性能强大。分布式易宽展。
  • ActiveMQ
Apache 出品 ,支持的协议比较多: AMQP 、STOMP 、MQTT、JMS。 java编写,可以将数据直接持久化到数据库中,可靠性比较低(发送的消息可能会丢失)
  • RabbitMQ
erlang语言编写,性能强,可靠性比较高
  • KafakaMQ
linkedin开源MQ,完全分布式架构,高吞吐量。设计之初是为了处理日志,一般作用于大量数据的数据收集业务。

北冥有只鱼
147 声望35 粉丝