消息队列 MQ 总结(入门)
序言
在实际开发环境中,你可能会遇到如下场景:
- 1.系统运行中会在特定时间产生了大量日志,日志服务的磁盘的IO 性能跟不上,导致某些服务运行缓慢。
- 2.某服务A的功能可能会调用服务B,但服务B的处理逻辑又与A无关(仅仅需要通知B处理下一些东西)
- 3.服务又注册用户机制,需要验证邮箱,但是处理和发送邮件占用了整个接口时间的2/3,但验证邮件并不是注册阶段验证的。
这些例子中,都存在AB两个独立服务,A是消息的发布者,B是消息的订阅者。实际环境中可能是一对多的关系(A对应多个B 或者A对应BCD多个不同的服务)
通过例子我们不难看出某些情况下,服务之间的调用存在一定的耦合性,但这种耦合性又是非必要的。因为被调用端的实际处理情况并不影响调用者的业务处理。
比如例子1中,写不写日志都不应该影响正常的功能运行【实现了削峰 解耦】,例子2里只是简单通知下B去处理,例子3中发邮件是注册用户所必须的,但不是注册用户接口中就必须要完成的,我可以延迟发送让接口响应的更快,提高体验。【实现异步 解耦】
我希望在这种弱关系的服务调用之间加一层隔离来实现解耦。这个时候我们旧可以应用消息队列了。
消息队列简单的讲就是是存在一张存放消息的链表,有一个异步的数据处理引擎接口消息,然后将这些消息分发到消息的处理者。如上图,这不就是典型的发布-订阅模式吗?我们使用消息队列隔离服务。比如日志处理场景中,应用服务只需要往队列里发日志就行了,不用去管谁会去处理,什么时候处理,日志服务也不用去管这是谁的日志,拿发来的日志,只管读取和写入就行。
至于消息队列和消费者怎么交互的,可以是消费者主动去消息队列里读取,也可以是消息队列主动发消息,具体支持情况需要看你用了哪个MQ实现了。
消息队列的应用场景
异步处理:例如短信通知、终端状态推送、用户注册、App推送等 数据同步:业务数据推送同步 重试补偿:记账失败重试 系统解耦:通讯上下行、终端异常监控、分布式事件中心 流量消峰:秒杀场景下的下单处理 发布订阅:HSF的服务状态变化通知、分布式事件中心 高并发缓冲:日志服务、监控上报
消息队列的基本概念
Broker
通俗的讲就是MQ的服务器
消息的生产者、消费者
消息生产者Producer:发送消息到消息队列。
消息消费者Consumer:从消息队列接收消息。
消息的ACK确认机制
当消费者确认消息已经被消费处理,发送一个ACK给消息队列,此时消息队列便可以删除这个消息了。如果消费者出现 宕机/关闭,网络中断等情况,没有发送ACK,消息队列将认为这个消息没有被处理,会将这个消息重新发送给其他的消费者重新消费处理。
消息的持久化
消息的持久化,对于一些关键的核心业务来说是非常重要的,启用消息持久化后,消息队列宕机重启后,消息可以从持久化存储恢复,消息不丢失,可以继续消费处理。
消息的事务支持
消息的收发处理支持事务,例如:在任务中心场景中,一次处理可能涉及多个消息的接收、处理,这处于同一个事务范围内,如果一个消息处理失败,事务回滚,消息重新回到队列中。
消息的数据结构
消息编码成字节数组的形式传递
消息积压
当消息发送速度大于接受处理速度的时候,就会发生小心积压。
消息大量积压后,当新的消费者连接上MQ并开始接收消息时,发送速率会大幅降低。
消息队列集群的压力增加,大量的消息要持久化存储和同步。
最后说下缺点:
- 可用性降低:本来系统好好的,非要加个MQ,如果哪天MQ挂了,那就呵呵了。
- 复杂性增加:一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。因此,需要考虑的东西更多,系统复杂性增大。