MQ消息队列理论

1. 消息队列的三个核心使用场景:解耦、异步、削峰
解耦
  • 假设A系统发送数据给BCD三个系统,通过接口发送数据,如果E系统也要找个数据,又或者B系统现在不需要这个数据了,那么A系统的逻辑代码会很复杂;

  • 这个场景中A系统与其他系统严重耦合,A系统产生一个关键数据,其他系统都需要A系统将数据发过来,A系统还需要考虑其中一个系统如果挂了该怎么办,要不要考虑重发,要不要把消息存起来等;

  • 如果使用MQ,A系统产生一条数据发送给MQ,哪个系统需要数据就自己去MQ里面消费,如果来了新系统,也可以直接去MQ里面进行消费,如果有系统不需要数据了,就直接取消对MQ的消费即可;

  • 这样一来,A系统完全不用考虑消息要发给谁,不需要维护这段代码,也不需要考虑其他系统是否调用成功/系统超时等问题;

  • 通过一个 MQ,Pub/Sub 发布订阅消息这么一个模型,A系统就跟其它系统彻底解耦了

异步
  • A系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求,等待个 1s,这几乎是不可接受的

  • 如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms,对于用户而言,其实感觉上就是点个按钮,8ms 以后就直接返回了

削峰
  • 每天 0:00 到 12:00,A 系统风平浪静,每秒并发请求数量就 50 个。结果每次一到 12:00 ~ 13:00 ,每秒并发请求数量突然会暴增到 5k+ 条。但是系统是直接基于 MySQL的,大量的请求涌入 MySQL,每秒钟对 MySQL 执行约 5k 条 SQL。

  • 一般的 MySQL,扛到每秒 2k 个请求就差不多了,如果每秒请求到 5k 的话,可能就直接把 MySQL 给打死了,导致系统崩溃,用户也就没法再使用系统了。

  • 但是高峰期一过,到了下午的时候,就成了低峰期,可能也就 1w 的用户同时在网站上操作,每秒中的请求数量可能也就 50 个请求,对整个系统几乎没有任何的压力。

  • 如果使用 MQ,每秒 5k 个请求写入 MQ,A 系统每秒钟最多处理 2k 个请求,因为 MySQL 每秒钟最多处理 2k 个。A 系统从 MQ 中慢慢拉取请求,每秒钟就拉取 2k 个请求,不要超过自己每秒能处理的最大请求数量就 ok,这样下来,哪怕是高峰期的时候,A 系统也绝对不会挂掉。而 MQ 每秒钟 5k 个请求进来,就 2k 个请求出去,结果就导致在中午高峰期(1 个小时),可能有几十万甚至几百万的请求积压在 MQ 中;

  • 这个短暂的高峰期积压是 ok 的,因为高峰期过了之后,每秒钟就 50 个请求进 MQ,但是 A 系统依然会按照每秒 2k 个请求的速度在处理。所以说,只要高峰期一过,A 系统就会快速将积压的消息给解决掉

2. 消息队列的缺点
系统可用性降低
  • 系统引入的外部依赖越多,越容易挂掉;本来你就是 A 系统调用 BCD 三个系统的接口就好了,没啥问题,你偏加个 MQ 进来,万一 MQ 挂了咋整,MQ 一挂,整套系统崩溃的,所以要确保消息队列的高可用性
系统复杂度提高
  • 硬生生加个 MQ 进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?头大头大,问题一大堆,痛苦不已
一致性问题
  • A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了
消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,系统复杂度提升了一个数量级,也许是复杂了 10 倍;但是关键时刻,用,还是得用的。
3. Kafka、ActiveMQ、RabbitMQ、RocketMQ 选择
  • ActiveMQ,现在大家用的不多了,没经过大规模吞吐量场景的验证,社区也不是很活跃

  • RabbitMQ,但是 erlang 语言阻止了大量的 Java 工程师去深入研究和掌控它,对公司而言,几乎处于不可控的状态,但是人家是开源的,比较稳定的支持,活跃度也高

  • RocketMQ,确实很不错(阿里出品),但社区可能有突然黄掉的风险,对自己公司技术实力有绝对自信的,推荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有活跃的开源社区,绝对不会黄

  • 中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择

  • 大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择

  • 大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

那一年,我也变成了光!!