Skip to content

Latest commit

 

History

History
154 lines (93 loc) · 7.11 KB

MQ-introduction.md

File metadata and controls

154 lines (93 loc) · 7.11 KB
title permalink categories tags comments date updated
mq-introduction
mq-introduction
program
MQ
true
2018-11-23
2018-11-23

MQ 简述

什么是MQ

消息队列(英语:Message queue)是一种进程间通信或同一进程的不同线程间的通信方式,软件的贮列用来处理一系列的输入,通常是来自用户。消息队列提供了异步的通信协议,每一个贮列中的纪录包含详细说明的数据,包含发生的时间,输入设备的种类,以及特定的输入参数,也就是说:消息的发送者和接收者不需要同时与消息队列互交。消息会保存在队列中,直到接收者取回它。

主流MQ

应用场景

当不需要立即获得结果,但是并发量又需要进行控制的时候,差不多就是需要使用消息队列的时候。

  • 异步处理
  • 应用解耦
  • 流量削峰
  • 其他

使用与否

  • 使用

譬如

  • 过安检,检测器处理能力有限,同时这些行李又不能丢了,加了个传送带,慢慢过检测器。其实这个传送带就是消息队列
  • 用户下单后,24小时未支付,需要取消订单。以前我们可能是定时任务循环查询,然后取消订单。实际上,我更推荐类似延迟MQ的方式,避免了很多无效的数据库查询,将一个MQ设置为24小时后才让消费者消费掉,这样很大程度上能减轻服务器压力
  • 帖子更新,关注者收到信息

场景举例

异步处理

  • 用户提交信息注册后,网站需要给用户发送邮件和短信

传统做法

将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端

image.png

不考虑网络等其他开销,耗费时间150ms

优化:

引入消息队列,用户的响应时间相当于是注册信息写入数据库的时间,也就是50ms。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50ms。

image.png

应用解耦

  • 凌晨进行数据统计task,这些task之间有一定的数据依赖关系

task3 需要使用task2的输出作为输入,task2 需要使用task1的输出作为输入,这样的话,tast1, task2, task3之间就有任务依赖关系,必须 task1 先执行,再 task2 执行,再 task3 执行。

不使用MQ

  • 方案
    1. task1,0:00 执行,经验执行时间为 50 分钟
    2. task2,1:00 执行(为 task1 预留 10 分钟 buffer),经验执行时间也是 50 分钟
    3. task3,2:00 执行(为 task2 预留 10 分钟 buffer)

image.png

  • 问题
    1. 如果有一个任务执行时间超过了预留 buffer 的时间,将会得到错误的结果
    2. 总任务的执行时间变长,总是要预留很多 buffer,如果前置任务提前完成,后置任务不会提前开始
    3. 如果有一个任务的执行时间要调整,将会有多个任务的执行时间要调整

使用MQ

  • 方案
    1. task1 准时开始,结束后发一个“task1 done”的消息
    2. task2 订阅 “task1 done” 的消息,收到消息后第一时间启动执行,结束后发一个 “task2 done” 的消息
    3. task3 订阅 “task2 done” 的消息,收到消息后第一时间启动执行
  • 优点
    1. 不需要预留 buffer,上游任务执行完,下游任务总会在第一时间被执行
    2. 依赖多个任务,被多个任务依赖都很好处理,只需要订阅相关消息即可
    3. 有任务执行时间变化,下游任务都不需要调整执行时间

MQ只用来传递上游任务执行完成的消息,并不用于传递真正的输入输出数据。

流量削峰

  • 系统A一天中大部分时间每秒请求并发数量就 100 多个,但是中午12点-1点每秒请求并发量就飙升到 10000 多个,但是系统每秒最大能处理的请求量只有 1000 多
  • 秒杀业务:上游发起下单操作,下游完成秒杀业务逻辑(库存检查,库存冻结,余额检查,余额冻结,订单生成,余额扣减,库存扣减,生成流水,余额解冻,库存解冻) 上游下单业务简单,每秒发起了10000个请求,下游秒杀业务复杂,每秒只能处理2000个请求,很有可能上游不限速的下单,导致下游系统被压垮

不使用MQ

过大流量引起服务器崩溃

使用MQ

image.png

将非即时处理的业务逻辑进行异步化

实例

某电商网站新手机发布在即,拥有预约码的用户可优先购买手机。预约方式为:注册账户即可获得预约码,预计预约用户超过1000万

像双11秒杀、手机预约抢购等对 IO 时延敏感业务环境下,当外部请求超过系统处理能力时,如果系统没有做相应保护,可能由于历史累计的超时请求负荷过多而导致系统处理的每个请求都因超时而无效,系统对外呈现的服务能力为 0,且这种情况下服务不能自动恢复。

image.png

这种情形下,引入MQ,将非即时处理的业务逻辑进行异步化。比如服务接收请求、处理请求和返回请求三个不同的业务逻辑。

引入 MQ 后,当预约活动开始时,海量并发访问汹涌袭来:

  • 所有客户的预约申请,页面均立即返回成功。客户便可关闭网页进行其他活动。预约码稍后推送到客户的邮箱/手机;

  • 超过千万级别的注册、预约申请,先暂存在 MQ 消息队列集群;

  • 后端服务进行处理,按照数据库实际的select、insert、update能力处理注册、预约申请;

  • 处理成功后返回结果给用户。预约结束后,用户大约在5-30min内,都收到了预约码。

引入MQ带来的问题

  • 可用性降低 系统引入的外部依赖越多,越容易挂掉,MQ 挂掉之后会导致整个系统不可用。

  • 复杂度提高 重复消费、消息丢失、消息的顺序性等这些都是引入 MQ 之后需要考虑的事情

  • 一致性问题

    A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,就会导致数据不一致

参考