为什么要使用消息队列?【3个常见的场景:解耦,异步,削峰填谷】
日常在使用DMS分布式消息中间件(消息队列)的时候,经常就是围绕它的能力去学习,但是为什么要使用它呢,常常因为太忙碌而没去注意。其实这是一个很关键的问题,我们为什么要使用消息队列?
如果我们是一家小公司,本身业务体量很小,很多事情单体架构单机就全解决了。但是后面因为业务快速发展,体量越来越大,受限于单体架构的缺陷,我们开始采用微服务的设计模式,采用分布式的架构来部署,拆分了很多服务。而随着业务场景越来越复杂,微服务数量越来越多,如何保障这些微服务之间通信的高效高质量呢?这时候就需要用到我们的消息队列了。
上面提到了越来越复杂的场景,最常见最核心的场景其实就3个:解耦、异步、削峰填谷。
解耦
第一个场景,服务A关联了4个服务:B,C,D;它们之间通过接口调用发送消息。我们因为业务需要,新增了2个服务E,F,它们也需要这个消息;此时,服务D又不需要消息了。。。
这么一波折腾,因为各个服务严重耦合在一起,A服务的研发团队肯定受不了,不仅要关注A服务本身,还需要维护各服务之间的调用、关注产生的消息有没有被需要的服务接受到:如果服务B/C/D/E/F挂了咋办,服务A需不需要重发,需不需要把消息存起来?
这时候,我们就需要引入消息队列了(Message Queue),它可以设置在服务A 和 这些服务之间。我们每次服务A产生了消息,直接发布给消息队列,然后就啥也不用管了。其余的服务,无论新旧,如果需要消费这个消息,就直接去消息队列订阅;如果不需要了,直接取消订阅即可。通过消息队列这个发布/订阅的模型,我们的服务A 就做到了和别的服务的解耦。
重点:服务耦合,要操心很多业务之外的事 -> 服务关注自身业务
异步
第二个场景,还是服务A,接收到了用户端发来的消息,需要对这个消息花费5ms处理一下(简化,保存之类的操作),之后将消息通过接口传递给服务B去处理(需要花费100ms处理),之后再发给服务C处理(需要200ms),再之后发给服务D处理(需要500ms)。这一连串事情处理下来,用户需要等5ms + 100ms + 200ms + 500ms = 805ms,这对于用户体验来说是不可接受的。
上述一连串调用在现实场景中其实是非常常见的,尤其是电商系统中,比如用户下单:支付处理-优惠券处理-积分处理-邮件通知等等。
那么我们该怎么优化呢?异步。我们在服务A处理完之后,马上把消息发给消息队列。服务B,C,D因为订阅了该消息,就会同时去消费,然后同时进行处理操作。而在用户看来,它只等了服务A处理的时间5ms + 发给消息队列的时间5ms = 10ms的时间,体验感受一下子就上来了。
重点:串行处理 -> 异步处理
削峰填谷
第三个场景,我们的业务因为是安防系统,白天风平浪静,流量很平稳,每秒并发请求数量就100条左右。但是到了夜晚、凌晨,流量就会爆发性的增长,每秒并发请求数量可能就会到达5K 条左右。我们当前的服务是直接连着数据库的,这么大的流量打进来,数据库肯定扛不住啊。于是我们就先引入了DCS缓存服务,让它先替数据库抗一下;一开始确实做到了,尤其是热点数据处理效率杠杠滴。但后来随着业务越做越大,凌晨每秒并发请求数量到达了2W 条左右,而且几乎没有什么所谓的热点数据(每个数据都会被平均的用到),连Redis也来不及处理了。
这时候怎么办呢?我们就要引入消息队列了。
在高并发流量打进来的期间(2W条/秒),系统就把消息直接发给消息队列。假设数据库加上缓存每秒可以处理请求6K 条,那么我们每秒就从消息队列里取出来6K条进行处理,保障服务遇到再大的高并发流量,都不会挂掉(削峰阶段)。而这些除了6K条以外的高峰期间的消息就会慢慢积压在消息队列里,越积越多;等到流量洪峰过去了,每秒恢复到就几百条流量进来的时候,我们就可以把这些积压的信息慢慢消费掉了(填谷阶段)。
重点:高并发流量超过数据库和缓存的处理上限 -> 消息队列对流量进行削峰填谷
- 点赞
- 收藏
- 关注作者
评论(0)