项目中用到了消息队列,但是自己还只是大概了解,于是打算系统的学习一下。学东西一定要注意体会思想,理解了思想就是学一通百,不注意理解思想,很容易就会淹没在技术的海洋中。
MQ与JMS
java是一个喜欢发布标准,让别人实现的语言,这个标准你可以理解为接口,像JDBC就是一组接口,由不同的数据库厂商负责实现,这是一个相当成功的设计。JMS也是类似于JDBC这样的标准,但是并没有做到像JDBC这么成功,所有的消息服务都按JMS来。
曾经的我以为MQ和JMS的关系是这样的:
像是接口和实现类一样,
但是实际上: 只有ActiveMQ完全遵守了JMS协议。RocketMQ、RabbitMQ、KafkaMq并不怎么遵守JMS。
JMS是什么?
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,完全分布式架构,高吞吐量。设计之初是为了处理日志,一般作用于大量数据的数据收集业务。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。