首页 > 其他分享 >我们为什么要用消息队列?

我们为什么要用消息队列?

时间:2023-03-05 09:23:17浏览次数:35  
标签:为什么 令牌 请求 队列 系统 订单 消息

消息队列是系统设计中存在时间最长的中间件之一,从系统有通信需求开始,就产生了消息队列。

消息队列的使用场景

在日常系统设计与实现的过程中,下面3种场景会涉及到消息队列:

  • 异步处理
  • 流量控制
  • 服务解耦

异步处理

典型的应用场景是秒杀系统,它要解决的核心问题是如何利用有限的服务器资源,尽可能多的处理短时间内的海量请求。

一般秒杀系统会包含下面的步骤:

  • 风险控制
  • 库存锁定
  • 生成订单
  • 短信通知
  • 更新统计数据

在没有引入消息队列时,上述5个步骤会依次执行,在引入消息队列后,只要风险控制和库存锁定完成,那么就可以返回用户秒杀成功,后面的步骤和秒杀没有直接关联,我们可以在库存锁定完成后,向消息队列中发送用户和商品信息,之后的子系统会读取消息队列的消息,进行后续处理。

这秒杀场景中引入消息队列,带来两个好处:

  1. 可以更快的返回结果。
  2. 减少等待,实现步骤之间并行处理,提升性能。

流量控制

一个设计健壮的程序有自我保护能力,在海量请求下可以在自身能力范围内尽可能多的处理请求,拒绝处理不了的请求并且保证自身运行正常。

还是以秒杀场景为例,我们可以进一步调整设计思路,使用消息队列隔离网关和后端服务:

  1. 网关收到请求后,将请求放入到请求消息队列。
  2. 后端服务从请求消息队列中获取APP请求,完成后续秒杀处理过程,然后返回结果。

这样当海量请求到来时,不会直接冲击到后端的秒杀服务,而是堆积在消息队列中,后端服务按照自己的最大处理能力,从消息队列中消费请求进行处理。对于超时的请求可以直接丢弃,APP可以将其视为秒杀失败。

这其实就是流量控制中的“漏桶流量控制”,网关在这里充当了”漏桶“的角色。

这样的设计可以根据下游的处理能力自动调节流量,达到”削峰填谷“的目的,但是有两个问题:

  1. 增加了系统调用链环节,导致总体响应时间变长。
  2. 上下游系统都要将同步调用改为异步调用,增加了系统复杂度。

我们还可以使用“令牌桶”来控制流量。它的原理是:单位时间内只发放固定数量的令牌到令牌桶中,规定服务在处理请求前必须先从令牌桶中拿出一个令牌,如果令牌桶中没有令牌,则拒绝请求。这样就保证在单位时间内,能处理的请求不超过发放令牌的数量。

令牌桶可以简单地用一个有固定容量的消息队列+一个“令牌发生器”来实现:令牌发生器按照预估的处理能力,匀速生产令牌并放入令牌队列(如果队列满了就丢弃令牌),网关在收到请求时到令牌队列消费一个令牌,获取到令牌则继续调用后端服务,如果获取不到则等待或者返回失败。

服务解耦

消息队列还可以起到服务解耦的作用,例如订单是电商系统中比较核心的数据,当创建一个新订单时:

  1. 支付系统需要发起支付流程
  2. 风控系统需要审核订单的合法性
  3. 客服系统需要给用户发送短信
  4. 经营分析系统需要更新统计数据
  5. 。。。。。

这些订单下游的系统都需要实时获取订单数据,随着业务发展,这些订单下游系统会不断增加,不断变化,并且每个系统可能只需要订单数据的一个子集,负责订单服务的开发团队不得不花费很大精力,应付不断增加变化的下游系统,不停修改调试订单系统与这些下游系统的接口。任何一个下游系统接口变更,都需要订单模块重新上线,这是不可接受的。

问题的解决办法是所有的下游系统可以通过消息队列来和订单系统通信,引入消息队列后,订单服务在订单变化时发送一条消息到消息队列,所有订阅相关主题的下游系统都可以实时获得一份完整的订单数据。

这样无论下游系统如何变化,订单服务都无需做任何更改,实现了订单服务和下游服务的解耦。

除了上述三种典型场景,消息队列还可以应用到:

  1. 作为发布/订阅系统实现一个微服务级系统间的观察者模式
  2. 连接流计算任务和数据
  3. 用于将消息广播给大量接收者

消息队列并不是“银弹”,下面的场景就不适合用消息队列:

  1. 实时响应要求高
  2. 数据强一致性要求高
  3. 不能容忍数据或者消息丢失

在引入消息队列后,也可能带来一些新的问题,包括:

  1. 异步通信带来的延迟问题
  2. 增加了系统设计的复杂度
  3. 可能会产生数据不一致的问题

标签:为什么,令牌,请求,队列,系统,订单,消息
From: https://www.cnblogs.com/wing011203/p/17179792.html

相关文章

  • P1160 队列安排
    P1160队列安排队列安排题目描述一个学校里老师要将班上N个同学排成一列,同学被编号为1~N,他采取如下的方法:先将1号同学安排进队列,这时队列中只有他一个人;2~......
  • java——spring boot集成kafka——消息队列的流派
                   ......
  • Java 集合 为什么重写 HashCode 和 equals
    #Java集合为什么重写HashCode和equals>Object源码中的HashCode和equals方法:>>```>publicnativeinthashCode();>>publicbooleanequals(Objectobj){>......
  • 为什么要做福禄克测试?
    什么是福禄克测试?福禄克网线测试是综合布线工程验收必要的测试,能测出网线通断情况,还能对其他十几项参数进行测试并给出专业测试报告,包括网线长度、传输时延、时延偏离、支......
  • C/C++ 数据结构优先级队列的实现(使用二级指针)
    #include<iostream>#include<Windows.h>#include<iomanip>//优先级队列的实现usingnamespacestd;#defineMaxSize5typedefintDataType;//队列中的元素类型......
  • 消息认证码
    消息认证码消息认证码的输入包含:任意长度的消息,密钥(发送者和接收者共享).输出:固定长度的密钥。消息认证码的主要功能:数据完整性:计算MAC时,将消息和密钥进行计算产生MAC值......
  • MySQL Delete 表数据后,磁盘空间并未释放,为什么?
    有开发小哥咨询了一个问题,记录一下处理过程分享给有需要的朋友。问题如下:MySQL数据库中有几张表增删比较频繁、数据变动剧烈且数据量大,导致数据增长过快,磁盘占用多。为了节......
  • 外观数列(字符串)、用队列实现栈、二叉树的序列化与反序列化(树、深度优先搜索)
    外观数列(字符串)给定一个正整数n,输出外观数列的第n项。「外观数列」是一个整数序列,从数字1开始,序列中的每一项都是对前一项的描述。你可以将其视作是由递归公式定......
  • 为什么编程是独一无二的职业
    1.有些人说编程很难,有些人认为很容易。编程不仅依赖于你的能力,而且还取决于你工作的态度。编程的确很难,但比起那些需要伪装、欺骗和表演来生活的恶棍或者小丑来说,真的一......
  • 基于API+MQ消息双链路数据同步中间件技术方案
    一、数据同步的背景及意义随着公司业务的发展,业务系统也会变得越来越复杂繁多,业务数据或分散、或冗余于各个业务系统中,增加了数据的管理难度和维护成本。因此,中心......