zoukankan      html  css  js  c++  java
  • 消息队列适合解决的问题

    一、异步处理

    秒杀系统需要解决如何利用有限的服务器资源,尽可能多地处理短时间内的海量请求

    处理一个秒杀请求包含步骤:

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

    能否决定秒杀成功,实际上只有风险控制和库存锁定这两步,当服务端完成前面2个步骤,确定本次请求的秒杀结果后,就可以马上给用户返回响应,然后把请求的数据放入消息队列中,由消息队列异步地进行后续的操作

    这样不仅响应速度更快,并且在秒杀期间,可以把大量的服务器资源用来处理秒杀请求。秒杀结束后再把资源用于处理后面的步骤,充分利用有限的服务器资源处理更多的秒杀请求。

    总结:在这个场景中,消息队列被用于实现服务的异步处理。这样做可以更快地返回结果,减少等待,自然实现了步骤之间的并发,提升系统总体的性能。

    二、流量控制

    继续以秒杀系统为例,一个设计健壮的程序有自我保护的能力,它应该可以在海量的请求下,还能在自身能力范围内尽可能多地处理请求,拒绝处理不了的请求并且保证自身运行正常。使用消息队列隔离网关和后端服务,以达到流量控制和保护后端服务的目的

    整个秒杀系统为:

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

    秒杀开始后,短时间大量的秒杀请求到达网关时,不会直接冲击到后端的秒杀服务,而是先堆积在消息队列中,后端服务按照自己的最大处理能力,从消息队列中消息请求进行处理。对于超时的请求直接处理为秒杀失败,运维人员还可以随时增加秒杀服务的实例数量进行水平扩展。

    这样做的优点是:能根据下游的处理能力自动调节流量,达到削峰填谷。缺点是:增加了系统调用链环节,导致总体的响应时延变长;上下游系统都要将同步改为异步消息,增加了系统的复杂度

    令牌桶流量控制

    令牌桶控制流量的原理是:单位时间内只发送固定数量的令牌到令牌桶中,规定服务在处理请求之前必须从令牌桶中拿出一个令牌如果令牌桶中没有令牌,则拒绝请求。这样就保证单位时间内,能处理的请求不超过发放令牌的数据,起到了流量控制的作用。

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

    三、服务解耦

    当一个新订单创建时:

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

    这些订单下游的系统都需要实时获得订单数据。随着下游系统不断的增加和变化,并且每个子系统可能只需要订单数据的一个子集,而订单服务需要不断跟着下游系统进行修改,这造成了系统耦合过于紧密的问题。

    引入消息队列,订单服务在订单变化时发送一条消息到消息队列的一个主题Order中,所有下游系统都订阅主题Order,这样每个下游系统都可以获得实时的订单数据。无论增加、减少下游系统或下游系统需求如何变化,订单服务都无需做任何更改,实现了订单服务与下游服务的解耦。

    四、其他场景

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

    消息队列自身的一些问题和局限性:

    • 引入消息队列带来的延迟问题
    • 增加了系统的复杂性
    • 可能产生数据不一致的问题。
  • 相关阅读:
    跨域常见解决方案
    express-session的简单使用说明
    Spring Cloud中,如何解决Feign/Ribbon第一次请求失败的问题?
    继承父类的静态方法的加载顺序
    sql索引优化
    EXPLAIN 执行计划详解
    JVM总括二-垃圾回收:GC Roots、回收算法、回收器
    dubbo知识体系
    Spring bean的生命流程
    日志体系与异常处理
  • 原文地址:https://www.cnblogs.com/chjxbt/p/11377402.html
Copyright © 2011-2022 走看看