消息队列。

消息队列。



why。

解耦。

eg. 物流系统发生故障,需要几分钟才能来修复,在这段时间内,物流系统要处理的数据被缓存到消息队列中,用户的下单操作正常完成。当物流系统恢复后,补充处理存在消息队列中的订单消息即可,终端系统感知不到物流系统发生过几分钟故障。

在这里插入图片描述

异步。

A 系统接收一个请求,需要在自己本地写库,还需要在 B、C、D 三个系统写库,自己本地写库要 3ms,B、c、D 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户体验非常不好,一般互联网类的企业,对于用户直接的操作,一般要求是每个请求都必须在 200ms 以内完成,对用户几乎是无感知的,如果用户通过浏览器发起请求,等待个 1s,这几乎是不可接受的。

在这里插入图片描述

如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms,对于用户而言,响应速度大大提升了,改善了用户的体验。

在这里插入图片描述

流量削峰。

应用系统如果遇到系统请求流量的瞬间猛增,有可能会将系统压垮。有了消息队列可以将
大量请求缓存起来,分散到很长一段时间处理,这样可以大大提到系统的稳定性和用户
体验。

一般情况,为了保证系统的稳定性,如果系统负载超过阈值,就会阻止用户请求,这会影响用户体验,而如果使用消息队列将请求缓存起来,等待系统处理完毕后通知用户下单完毕,这样下单体验要好。

在这里插入图片描述

流量削峰的经济考量。

业务系统正常时段的 QPS 是 1000,流量最高峰是 10000,为了应对流量高峰配置高性能的服务器显然不划算,这是可以使用消息队列对峰值流量削峰。



MQ 对比。

特性ActiveMQRabbitMQRocketMQkafka
开发语言JavaerlangJavaScala
单机吞吐量万级万级十万级十万级
时效性ms 级us 级ms 级ms 级以内
可用性高(主从架构)高(主从架构)非常高(分布式架构)非常高(分布式架构)
功能特性成熟的产品,在很多公司得到应用。有较多的文档。各种协议支持较好。基于 erlang 开发,并发能力强,性能好,延时低。管理界面丰富。MQ 功能比较完备,扩展性好。只支持主要的 MQ 功能,像一些消息查询、消息回溯功能没有提供,大数据领域应用广。
  • 高可用。

RabbitMQ ~ 镜像集群。
RocketMQ ~ 双主双从。



消息丢失。

在这里插入图片描述



消息重复消费。消息幂等性问题。

消息重复的根本原因是网络不可达。

  • 发送时消息重复。

当一条消息已被成功发送到服务端,此时出现了网络闪断,导致服务器对客户端应答失败。如果此时生产者意识到消息发送失败并尝试再次发送消息,消费者后续会受到两条同同样的消息。

在这里插入图片描述

  • 消费消息时重复。

消息消费场景下,消息已经投递到消费者并完成业务处理,当消费方给 MQ 服务器反馈应答时网络闪断。为了保证消息至少被消费一次,MQ 服务器在网络恢复后再次场次投递之前已被消费方处理过的消息,此时消费者就会收到两条相同的消息。

在这里插入图片描述

  • 解决。
  • 消息发送者发送消息时携带一个全局唯一的消息 id。
  • 消费者获取消息后先根据 id 在 Redis / db 中查询是否存在消费记录。
  • 如果没有消费过就正常消费,消费完毕后写入 Redis / db。
  • 如果消息消费过就直接舍弃。


消息消费顺序性。

一笔订单产生了 3 条消息,订单创建,订单付款,订单完成。

消费时要按照顺序依次消费。

与此同时多笔订单间又是可以并行消费的。

张三:订单完成,订单付款,订单创建。
李四:订单完成,订单付款,订单创建。

  • 模型:M1 M2 按照先后顺序发送到 2 台 server,被两个消费者分别消费。(×)。

不能保证消息的顺序到达 MQ。
不能保证消息的顺序消费。

  • 模型:M1 M2 按照先后顺序发送到 1 台 server,被两个消费者分别消费。(×)。

顺序到达可以保证。
不能保证顺序消费。

  • 模型:生产者:MQ Server,消费者:1:1:1。

可以保证,但慢。(全局顺序性)。

吞吐量下降。
容错性降低。

在这里插入图片描述

  • 模型 ~ 局部顺序消费。

生产者根据消息 ID 将同一组消息发送到一个 Queue 中。
多个消费者同时获取 Queue 中的消息进行消费。
MQ 使用分段锁保证单个 Queue 中的有序消费。

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_3");
        consumer.registerMessageListener(new MessageListenerOrderly() {

            @Override
            public ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext consumeOrderlyContext) {
                for (MessageExt messageExt : list) {
                    // 业务处理。

                }
                return ConsumeOrderlyStatus.SUCCESS;
            }
        });


MQ 实现分布式事务。

  • 消息发送方。

处理业务逻辑。
保存消息到本地数据库。
发送消息给 MQ。
监听 MQ 消息方通知消息,更改消息状态为已处理。
定时任务将长期未处理的消息发送到 MQ。

  • 消息消费方。

监听 MQ 中间件消息。
判断消息是否重复,重复就丢弃。
消息不重复,执行本地任务。
业务处理完毕,写消息记录到本地数据库。
发送通知消息到 MQ。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lyfGeek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值