RocketMQ(四)----- RocketMQ的高级特性***

本篇总结了RocketMQ在发送消息过程中的各方面细节:

一、MQ消息发送的可靠性问题与解决

对于消息的安全性在前面MQ篇(一)已经介绍过,主要涉及:

  1. 消息确认机制(贯穿整个发送过程)
  2. 消息在MQ队列中的持久化(MQ正确保存)
  3. 消息重试机制(为了保证发送到消费者)

但是这个做法并不能保证消息在此过程中正确送达,所以催生下面的细节问题。

二、MQ对消息的持久化

一、中涉及了MQ在队列中对消息进行保存,下面分析为什么要持久化数据:

如果MQ不对消息进行持久化保存,那么从生产者发送给消费者的消息

  1. 一旦MQ发生宕机,下次重启之后消息将全部消失(保证消息不丢失的角度考虑)
  2. 如果不进行持久化保存,那么有可能造成生产者将消息重复发送给MQ(生产者发送消息给MQ,MQ由于网络原因并未返回确认给生产者,那么生产者重复发送,于是MQ队列中存放两条相同的消息,进而消费者重复消息)(重复消费角度的角度考虑)

于是,如何处理能够解决这两个问题?

就是将消息持久化保存到中间数据库中:

  1. 防止消息在MQ丢失
  2. 从生产者发送来的消息,首先进行持久化,并且配置了唯一键索引,如果触发唯一冲突,那么该消息已经存在,避免来自生产者消息的重复性

进一步分析:在mysql中,所有的数据其实是保存在文件中(mysql将消息保存在binlog日志文件中),那么这里保存到数据库,其实也是保存到文件:

进而引出下面问题三

三、Rocket采用更高效的持久化技术

既然最终消息保存在文件中,那么不如一开始就不通过数据库,而是直接保存到文件,Rocket通过两种方式提高消息持久化的速度:

1.用顺序写入的方式,数据不是一块一块地写入,而是预先申请一片连续的存储空间,后续直接写入即可

2.零拷贝技术

四、消息的存储结构:

在MQ中,消息被保存到commitlog文件中。这里主要负责以多队列的方式存放消息

RocketMQ 中:

所有 Topic 的所有 Queue 的消息,统统写在同一个 CommitLog 文件序列中

也就是说:

TopicA.Queue0 → 写入 CommitLog

TopicA.Queue1 → 写入 CommitLog

TopicB.Queue0 → 写入 CommitLog

消费者读取消息绑定的是topic,但是消息实际上被保存在topic的queue中,那么消息被push给消费者之后,就需要记录消费者当前读取到了哪个massageQueue的哪条消息

所以,需要有一个偏移量,记录当前是哪个队列,队列中的哪条消息。

那么既然知道了消息最终是要保存到磁盘中的(保存到内存肯定不安全),那么是立即保存? 还是有规律的保存,这就涉及到刷盘方式

五、刷盘机制

正常情况是消息一旦到来为了安全性直接开启持久化操作:

但是这种方式最耗费资源,所以也存在如“异步刷盘”的方式:

那么当前MQ已经能够尽可能地:

  1. 保证消息不丢失(持久化消息)
  2. 同时高效持久化(文件写入方式+刷盘机制)

但是引入了中间件,就需要确保中间件的高可用性(尽可能不宕机),那么如何保证MQ的高可用性?(不经常宕机)

六、MQ的高可用

我们知道mysql为了保证高可用性采用了分库+主从复制,那么其实在这里也可以通过设置MQ集群的方式来保证高可用性:

那么MQ的结构中包含四个角色,因此可以从四个方面来阐述MQ的集群:

对于主从复制,同样有同步复制与异步复制之分,具体按照开发需求使用

那么开启集群之后,比如MQ(broker就有多个了,生产者往哪个发?就是问题,之前阐述MQ架构的时候,就知道同一个topic可能绑定在不同的broker上,所以生产者发送消息如果broker如果开启了集群,那么其实可以发送到不同的broker上)

此时就涉及到:什么时候忘哪个发?这个做法相信我们已经有想法了,这个时候一般会采用负载均衡的方式:如果某个broker挂掉,还能够有broker接收

对于消费者端,同样存在负载均衡,尽可能要让同一个broker都能指向消费者集群的不同消费者,为了在某个broker挂掉之后,还能够正确发送给消费者。

七、消息重试策略

在之前分析消费从MQ到消费者的过程中,如果消费者返回ACK失败,怎么办? MQ采用了一种重试机制,并将重复尝试但还是失败的消息放入死信队列,交给开发者处理,下面做具体分析:

这个过程实际上分为:

  1. 顺序消息重试
  2. 无序消息重试

如果是顺序消息,重复发送仍然失败,导致队列的offset不发生变化,就可以对此进行监控,通知开发者处理。

如果是无序消息,就采用之前的放入死信队列的方式:

当消息消费重试到达了指定次数(默认16次)后,MQ将无法被正常消费的消息称为死信消息(Dead-LetterMessage)死信消息不会被直接抛弃,而是保存到了一个全新的队列中,该队列称为死信队列(Dead-LetterQueue)

死信队列特征

  • 归属某一个组(GourpId),而不归属Topic,也不归属消费者
  • 一个死信队列中可以包含同一个组下的多个Topic中的死信消息
  • 死信队列不会进行默认初始化,当第一个死信出现后,此队列首次初始化

死信队列中消息特征

  • 不会被再次重复消费
  • 死信队列中的消息有效期为3天,达到时限后将被清除

=================================================

本节内容是MQ发送消息整个过程中的细节内容,关于MQ消息的幂等性保证,单独放在下一节。

=================================================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值