面向面试编程:消息队列——优缺点

106 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情

面试官:为什么使用消息队列?

消息队列常见场景

解耦

不用MQ时,A系统严重跟其它系统耦合,A系统产生了一个比较关键的数据,其他系统需要A系统将这个数据发送过来,此时A系统还需要考虑各种系统的出现异常的情况(系统挂了、连接超时、重试等机制)。

使用MQ的解耦场景,A系统将产生的数据发送到MQ里面去,那个系统需要数据就自己去MQ里去消费,如果有新的系统需要数据,自己直接去MQ里消费即可,如果正在消费的某个系统不需要消费数据了,取消对MQ的消费即可,A系统不需要考虑要给谁发送数据,不需要维护代码,不需要考虑其它系统出现异常的情况。

异步

不用MQ的同步高延时场景,用户对系统A发起一个请求:

  • 在A系统本地数据库执行一个sql(20ms);
  • 调用B系统接口,B系统数据库执行3条sql(100ms);
  • 调用C系统接口,C系统数据库执行4条sql(150ms);
  • 调用D系统接口,D系统数据库执行2条sql(80ms);

总时长350ms(一般互联网企业对用户的直接操作,一般要求每个请求必须在200ms以内完成,对用户几乎无感知)。

使用MQ异步化之后的接口性能优化,用户发起一个请求给A系统:

  • A系统在自己本地执行一个sql(20ms);
  • 发送连续三条消息到三个队列中(5ms);
  • 每个系统自己去对应的MQ中消费对应的消息,从中提取参数在自己本地数据库执行对应的操作;

总时长25ms(A系统无需等待其它系统消费完成,直接返回给用户)。

削峰

未使用MQ高峰期系统被打死场景:

  • 大量用户(100万)通过浏览器在中午高峰期同时进行大量的操作;
  • 大量的请求涌入我们的系统中,假设高峰期每秒5000个请求;
  • 系统是直接基于Mysql的,大量请求打过来,每秒执行5000条sql,系统崩溃(正常MySQL可以抗住2000/s,此时会将MySQL打死);
  • 中午高峰期过了之后,下午为低峰期,每秒50个请求,几乎没有压力;

使用MQ来解决,进行削峰:

  • 大量用户中午操作,假设每秒5000请求;
  • 每秒5000个请求写入MQ中;
  • A系统每秒钟最多只能处理2000个请求(MySQL每秒2000个);
  • A系统从MQ中慢慢拉取请求,每秒2000个,不要超过自己的最大处理数;
  • MQ每秒钟5000个请求过来,2000个请求出去,导致高峰期在MQ中积压几十万到几百万请求;
  • 高峰期过去之后,每秒进50个请求,但A系统还是按每秒2000个请求来处理,所以高峰一过,A系统会很快将积压的消息解决掉;

消息队列缺点

面试官:刚刚说的都是MQ的优点,那引入MQ有什么缺点吗?

系统可用性降低

MQ一旦故障了,A系统无法发送消息到MQ,其他系统无法消费到消息,整个系统就崩溃了,无法运转。

系统复杂性提高,导致系统需要考虑的问题变多

A系统本来就给B系统发一条数据就可以了,结果因为A系统与MQ之间协调出现问题,发送了两次,导致B系统内部插入了2条数据。

一致性问题

有人给A系统发送个请求,本来这个请求应该时ABCD四个系统都执行成功才能返回的,结果ABC三个系统都执行成功了,但是D系统执行失败了,就导致整个请求给用户返回是成功,结果后台逻辑没有完全执行完。