消息队列高手课——01 | 为什么需要消息队列?
- 哪些问题适合使用消息队列来解决?
- 1. 异步处理
- 秒杀系统,需要消息队列
- 秒杀系统需要解决的核心问题是,如何利用有限的服务器资源,尽可能多地处理短时间内的海量请求
- 对于这 5 个步骤来说,当服务端完成前面 2 个步骤,确定本次请求的秒杀结果后,就可以马上给用户返回响应,然后把请求的数据放入消息队列中,由消息队列异步地进行后续的操作
- 在这个场景中,消息队列被用于实现服务的异步处理。这样做的好处是:
- 可以更快地返回结果;
- 减少等待,自然实现了步骤之间的并发,提升系统总体的性能
- 秒杀系统,需要消息队列
- 2. 流量控制
- 如何避免过多的请求压垮我们的秒杀系统?
- 我们的设计思路是,使用消息队列隔离网关和后端服务,以达到流量控制和保护后端服务的目的
- 方法一
- 加入消息队列后,整个秒杀流程变为:
- 1、网关在收到请求后,将请求放入请求消息队列;
- 2、后端服务从请求消息队列中获取 APP 请求,完成后续秒杀处理过程,然后返回结果。
- 秒杀开始后,当短时间内大量的秒杀请求到达网关时,不会直接冲击到后端的秒杀服务,而是先堆积在消息队列中,后端服务按照自己的最大处理能力,从消息队列中消费请求进行处理。
- 对于超时的请求可以直接丢弃,APP 将超时无响应的请求处理为秒杀失败即可。运维人员还可以随时增加秒杀服务的实例数量进行水平扩容,而不用对系统的其他部分做任何更改。
- 这种设计的优点是:能根据下游的处理能力自动调节流量,达到“削峰填谷”的作用。但这样做同样是有代价的:
- 增加了系统调用链环节,导致总体的响应时延变长。
- 上下游系统都要将同步调用改为异步消息,增加了系统的复杂度。
- 加入消息队列后,整个秒杀流程变为:
- 方法二
- 如果我们能预估出秒杀服务的处理能力,就可以用消息队列实现一个令牌桶,更简单地进行流量控制
- 令牌桶控制流量的原理是:单位时间内只发放固定数量的令牌到令牌桶中,规定服务在处理请求之前必须先从令牌桶中拿出一个令牌,如果令牌桶中没有令牌,则拒绝请求。
- 这样就保证单位时间内,能处理的请求不超过发放令牌的数量,起到了流量控制的作用
- 实现的方式也很简单,不需要破坏原有的调用链,只要网关在处理 APP 请求时增加一个获取令牌的逻辑
- 令牌桶可以简单地用一个有固定容量的消息队列加一个“令牌发生器”来实现
- 令牌发生器按照预估的处理能力,匀速生产令牌并放入令牌队列(如果队列满了则丢弃令牌)
- 网关在收到请求时去令牌队列消费一个令牌,获取到令牌则继续调用后端秒杀服务,如果获取不到令牌则直接返回秒杀失败
- 如果我们能预估出秒杀服务的处理能力,就可以用消息队列实现一个令牌桶,更简单地进行流量控制
- 以上是常用的使用消息队列两种进行流量控制的设计方法,你可以根据各自的优缺点和不同的适用场景进行合理选择
- 如何避免过多的请求压垮我们的秒杀系统?
- 3. 服务解耦
- 消息队列的另外一个作用,就是实现系统应用之间的解耦
- 订单是电商系统中比较核心的数据
- 订单下游的系统都需要实时获得订单数据
- 随着业务不断发展,这些订单下游系统不断的增加,不断变化
- 任何一个下游系统接口变更,都需要订单模块重新进行一次上线,对于一个电商的核心服务来说,这几乎是不可接受的
- 所有的电商都选择用消息队列来解决类似的系统耦合过于紧密的问题
- 引入消息队列后,订单服务在订单变化时发送一条消息到消息队列的一个主题 Order 中
- 所有下游系统都订阅主题 Order,这样每个下游系统都可以获得一份实时完整的订单数据
- 无论增加、减少下游系统或是下游系统需求如何变化,订单服务都无需做任何更改,实现了订单服务与下游服务的解耦
- 1. 异步处理
- 小结
- 以上就是消息队列最常被使用的三种场景:异步处理、流量控制和服务解耦。当然,消息队列的适用范围不仅仅局限于这些场景,还有包括:
- 作为发布 / 订阅系统实现一个微服务级系统间的观察者模式;
- 连接流计算任务和数据;
- 用于将消息广播给大量接收者
- 同时我们也要认识到,消息队列也有它自身的一些问题和局限性,包括:
- 引入消息队列带来的延迟问题;
- 增加了系统的复杂度;
- 可能产生数据不一致的问题
- 以上就是消息队列最常被使用的三种场景:异步处理、流量控制和服务解耦。当然,消息队列的适用范围不仅仅局限于这些场景,还有包括:
行者无疆,始于足下
行走,思考,在路上