导语
什么是消息队列,消息队列解决了什么问题?
什么是消息队列?
消息队列(Message Queue),广义上就是支持消息队列处理的中间件,提供了完整的消息生产、消费、消息存储的软件系统结构。如下图所示
但实际上消息队列的功能远远不止这些,其本质是两个进程之间传递信息的一种方式。两个进程可以分布在同一个机器上,也可以分布在不同的机器上。
进程通信可以通过RPC(Remote Procedure Call,远程过程调用)的方式进行。那么消息队列存在的意义是什么呢?
简单举个例子。
过年回家买票,当你打开12306 App的时候,操作如下
- 第一步、输入出发地、目的地、出发时间等信息
- 第二步、点击“预订”按钮,这个时候12306的页面就开始转圈圈了,与此同时,还有其他人跟你一样,也在买同样的车票。
- 第三步、过了一段时间之后,你的APP提示你购票失败
- 第四步、你修改车次,然后重新发送订票的请求,又过了一段时间之后,APP提示购票成功。
如下图所示
在整个的购票过程中,12306会遇到如下的一些问题。
- 1、今天的车次只有3000张票,但实际上需要购票的人事100W,如果一个一个请求的处理,那么这个等待量将会是非常大的,如何解决?
- 2、后续有很多的系统在等待购票的结果,如果购票成功之后,这些系统将会进行后续的处理,失败之后,这些系统又将如何处理?
- 3、12306的购票结构一直在发生变化,一直在优化,那么下游系统是否会一起跟着变化?
上面的这三个问题只是常见的三个问题,那么对于其他的很多的这样的不确定的问题,该如何解决呢?这就有了消息队列的出现。
为什么需要消息队列呢?
流量削峰
我们知道12306应该是全国最大的存在超高并发的实战场景。在购票的高峰时段,由于后端的服务来不及处理过多过快的请求,可能就会导致请求阻塞,严重的会导致服务宕机。
在实际场景中,我们都希望流量可以像是图中的虚线一样,比较平稳。这样系统的稳定性就可以得以保障。但实际上,系统流量会随着时间的变化不断的变化。像是12306这样的APP在春运时段的流量应该是很难想象的。但是对于春运这样的大流量时段并不是一直都存在的。所以,我们可以通过扩展服务器配置的方式来解决这个问题。
服务器扩展的方式优势是显然易见的,但是缺点也是比较明显,流量的低谷期,服务的使用是相对闲置的,是极大的资源浪费。
如何平衡空闲时间与高峰时段呢?于是消息队列就起到了作用。在订票消息进入到消息队列之后,会告诉用户30分钟之后会告诉他订票的结果,这个时候就服务器就有时间来处理消息队列中的消息,但是消息队列的优缺点也是显然的。虽然性能提升了,但是开发人员还需要维护一个消息队列,这个时候就出现了消息中间件的概念。
程序解耦
不同的业务端在进行联合开发的时候,由于排期的不同,人员调配不便等因素导致项目延期的例子在软件开发中屡见不鲜。其根本的原因就是系统耦合度过高。如何解决这个问问题呢?
如下图所示,上下游的业务之间的通信是彼此依赖的,所以不得不去协调上下游所有的资源进行同步开发,这个时候跨团队的成本就比较高了。
不知道是否遇到过另一个团队调用你的API,你告诉他发个请求过来,然后你打着断点一步一步调试的场景么? 你是否借的协调开发资源、QA资源,以及上线之前做的所有等待的一切么?最后项目还是延期,相互之间依赖太严重。
如果加入消息队列之后就不一样了,如下图所示。上下游的系统进行开发、联调、上线,完全不依赖其他系统功能是否存在。只要按照约定的方式进行开发即可。
异步处理
处理订票请求是一个非常漫长的过程,大家都有过排队买票的经历,从查票、下单、减扣库存、更新缓存、到购票成功,这些都是耗时的操作。可以通过消息队列的方式把知道购票的请求提交成功的请求告诉用户,然后异步处理后续的等待操作,并且保证在30分钟之内将所有的处理操作结果通过短信的方式告诉用户。这样就可以实现异步处理操作。
数据的最终一致性
如图所示。每个月都会发工资,如何将自己的工资从招行转到北京银行。
解决数据最终一致性的方案,业内使用比较多的手段就是消息队列。
- 1、免去了招行APP多次重试请求的复杂逻辑
- 2、免去了北京银行APP处理多次请求的压力
- 3、即使北京银行的服务不可用也不会影响整个的业务,在服务可用的时候,会进行消息的补偿。然后告诉招行扣款成功。
常见的消息队列