zoukankan      html  css  js  c++  java
  • 消息队列

    消息队列的使用场景

    参考文章:消息队列使用的四种场景介绍

    1. 异步处理 / 最终一致性

    非重要业务场景异步处理,提高接口响应速度。一个订单流程是非常长的,下单过程中需要各种校验、扣减商品库存、扣减服务者排班等,此时类似于下单短信或者微信模板消息等推送,就可以异步处理,将要发的短信内容和接收人信息等以MQ形式发出去,然后接收到短信后,再给用户发送。

    允许非强一致性出现,主要保证最终一致性即可。

    2. 应用解耦 / 消息广播

    一对多:

    订单完成时,可能积分系统需要给用户发积分,用户画像系统可能会给用户打上近期有完成单标签,优惠券系统可能需要给用户发券诱导再次下单等。此时对订单系统来说,将会有多个下游。此时订单系统就可以不关注下游信息,而将必要的订单信息通过MQ形式通知出去,相应的业务系统自己接受信息即可。

    多对一:

    用户画像系统需要实时记录用户定位城市,作为一种用户标签,服务于精准用户营销。此时,对于用户画像系统,是多端上游,上游比如有小程序、微信公众号、微信钱包、集团APP定位、业务线APP定位、外接纯H5定位等。而且对于这些多端来说,同步用户定位城市并非是它们的主流程,此时就可以由用户画像系统定义统一数据接收格式,多端按照此格式在定位成功后通知用户画像系统。

    流量削峰

    image.png-88.5kB
    image.png-102.7kB

    日志处理

    日志处理是指将消息队列用在日志处理中,比如kafka的应用,解决大量日志传输的问题。架构图如下:

    image.png-9.2kB

    • 日志采集客户端,负责日志数据采集,定时写受写入Kafka队列
    • Kafka消息队列,负责日志数据的接收,存储和转发
    • 日志处理应用:订阅并消费kafka队列中的日志数据

    重试定时任务

    此类主要是针对于延迟消息应用场景。在业务上遇到的场景是:支付成功后,需要回调业务线告知订单支付成功,业务线需要完成自己的订单以及按照自己的各种策略给商家结算,但是由于业务线处理流程非常长或者其他原因,时有回调失败的情况,且业务上不允许出现回调失败的情况,因为回调失败会影响到商家结算、商家账户收入等。但是回调失败的场景并不多见,平均一个月两三次。为了解决这个问题,就可以使用延迟消息队列,当回调失败时,先计算回调次数和回调延迟时间(这个延迟时间可以根据回调次数增大而增大),指定时间后接收到延迟消息再次给业务线尝试通知支付成功重试。

    消息乱序解决思路

    1. 丢弃旧消息

    • 适用场景:
      针对于只关注最终结果的用户场景。

    • 业务场景:
      营销部门需要接收用户打开APP的每次城市定位信息形成城市定位用户标签,此时对于营销部门只关心用户最后的城市定位消息。

    • 解决思路:
      强制发送方在消息体内加入一个时间戳,接收方接收到信息 处理成功后会落库。此时一条消息到达后,先验证是否有同一个用户但是时间戳更大的消息被消费成功了,如果有,则说明先发的消息延迟到达了,此时就可直接忽略时间戳更小的消息,因为我们只需要关注最新的消息即可。

    2. 消息编排

    以下单整个流程为例,下单消息、支付消息、退款消息是要求顺序到达的,不能退款消息在支付消息之前到达,此时业务无法处理。

    • 解决思路
    1. 按照业务先后顺序,人为消息编排:下单消息编号为1,支付消息为2,退款消息为3。
    2. 消息处理成功后,会保证落库成功。
    3. 一条消息到达后,会先检查前置消息是否消费成功(比如 支付的前置消息就是下单,退款的前置消息就是支付),只有前置消息消费成功后才进行本条信息消费。
    4. 如果前置消费根本就没有消费或者消费失败还在重试阶段,就先落库,然后ACK消息,不消费此条信息。
    5. 每条消息消费成功后,会先检查是否有后置消息需要消费,如果有则递归进行消费。

    3. 消息间解耦

    还是以下单流程为例,支付消息是可能会在下单消息之前到达,也就是消息间是耦合的,顺序是不能被打断。但是对于异步消息队列来说,我们无法保证顺序。

    所以,我们可以在发送一条信息时带上全部前置消息的必要信息,比如退款消息,消息体中就可以带上必要的订单信息和支付信息;如果觉得这样消息体很大时,也可以只带上相应主键,比如订单id、支付记录Id等,然后反查补全消息消息时必须的信息。

    消息的幂等性解决思路

    可以由发送方在消息体内加上消息的一个全局唯一编号,接收方在接收到信息后,先使用分布式锁,以这个全局唯一编号作为key去加锁,加锁成功后,再验证是否有这条消息的成功消费记录,如果有则代表消息已被消费,直接ACK消息。如果没有则进行消息消费,消费成功后消息落库,释放锁。

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    关于模态/非模态对话框不响应菜单的UPDATE_COMMAND_UI消息(对对WM_INITMENUPOPUP消息的处理)
  • 原文地址:https://www.cnblogs.com/boothsun/p/8637933.html
Copyright © 2011-2022 走看看