中间件
什么是中间件:连接多个系统,帮助多个系统紧密协作的技术。
常用的中间件:Redis、消息队列、分布式存储等
消息队列
- 存储消息的队列
关键词:存储、消息、队列
存储:存储数据
消息:某种数据结构,比如字符串、对象、二进制数、Json等
- 应用场景(作用):
在多个不同的系统中,应用之间实现消息的传输(也可以存储)。不需要考虑传输应用的编程语言、系统、框架等。比如可以让Java开发的应用发消息,PHP开发的应用收消息,这样就不需要将所有的代码都写到一个项目里(应用解耦)。
消息队列的模型
- 生产者:Productor,类比为快递员
- 消费者:Consumer,类比为取快递的人
- 消息队列:Queue
- 消息:Message。类比为快递,生产者要传输给消费者的数据
为什么不直接传输,要用消息队列?
生产者不用关心消费者需不需要消费,只要将消息放入消息队列中任务就完成了,这样将生产者和消费者之间实现了解耦,互不影响。不同的生产者也可以在消息队列中放不同的消息。
为什么要用消息队列?
1.异步处理
生产者可以发送完消息后,去忙别的事情。消费者想什么时候消费都可以,不会产生阻塞的情况。
2.削峰填谷
先把用户的请求放到消息队列中,消费者(实际操作的应用)可以按照自己的需求慢慢去取。
情景:当在12点中突然来了10万个请求,流量突刺,10万个请求系统内部处理,容易出现宕机情况。使用消息队列,消费者根据系统按照一定的速率进行消息的处理(比如说1秒中处理1条数据)从而保证了系统的稳定性。
分布式消息队列的优势
1)数据持久化:可以把数据存储在硬盘里,服务器重启数据就不会丢失
2)可扩展性:可以根据需求,随时增加(或者减少)节点、继续保持稳定的服务
3)应用解耦:可以连接各个不同的语言、框架开发的系统,让这些系统能够灵活传输读取数据
使用消息队列进行应用解耦:
应用场景:
在一个订单系统中,有库存系统,发货系统等。相比于传统的直接调用的方式,订单系统来了一个订单要给库存系统和发货系统发送消息。
以前,把所有的功能都放到同一个项目中,调用多个子功能,一个环节错就整体都出错
使用消息队列来进行解耦,订单系统将消息发送完后就立刻返回。一个系统挂了,不会影响其他系统的运行,如果后面被挂的系统又重新复活执行业务逻辑,重新运转。
使用消息队列进行解耦的优势:
- 一个系统挂了,不会影响另外的系统的运行
- 系统挂了后期恢复,仍然能继续执行业务逻辑
- 不用管是否最终执行成功,只需要发送一个消息到队列,就立刻返回,不用同步调用所有的系统,性能更高。(秒杀系统)
4)消息订阅
应用场景:当一个很大的系统,需要向下面的小系统发送消息,最简单和直接的方式就是依次调用小系统。但是会出现很多问题:
1、调用系统耗时会很长,每次都要调用很多系统,有可能失败,性能不好。
2、不知道小系统是否需要,或者说如果一个新的项目出现,但是大项目感知不到,无法发送订阅消息。
解决方案:大的核心系统始终往一个地方(消息队列中)发送消息,其他系统都去订阅这个消息队列(读取这个消息队列中的消息)
消息队列的应用场景:
- 耗时的场景(异步)
- 高并发(异步、削峰填谷)
- 分布式系统协作(尤其是跨团队、跨业务协作、应用解耦)
- 强稳定性的场景(比如金融业务、持久化、可靠性、削峰填谷)
消息队列的缺点:
- 要引入额外的中间件,系统更复杂,维护费用、部署成本
- 有可能出现消息丢失,顺序性,重复消费,数据的一致性(分布式系统就要考虑)
主流分布式消息队列选型:
- activeMQ
- rabbitMQ
- kafka
- rocketMQ
- zeroMQ
- plusar
- Apache InLong(Tube)
技术选型维度:
- 吞吐量:IO、并发
- 时效性:消息发送到达时间,越高越快
- 可用性:系统可用的比率(比如1年365天宕机1s)
- 可靠性:消息不丢失,功能正常完成