[关闭]
@boothsun 2018-04-24T15:54:20.000000Z 字数 1989 阅读 1206

消息队列(已完)

面试题


消息队列的使用场景

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

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

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

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

2. 应用解耦 / 消息广播

一对多:

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

多对一:

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

3. 流量削峰

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

4. 日志处理

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

image.png-9.2kB

5. 重试定时任务

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

消息乱序解决思路

1. 丢弃旧消息

2. 消息编排

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

3. 消息间解耦

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

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

消息的幂等性解决思路

  1. 业务去重 幂等

    比如订单支付消息,一个订单正常业务场景下,只能支付一次,同样也只能接收到一条支付消息。所以,如果实际确实收到了两条消息,对于第二条消息可以抛弃或者打Error日志。

  2. 人为全局唯一编号:

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

其他消息相关知识点

https://www.w3cschool.cn/architectroad/architectroad-message-queue.html

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注