- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章RocketMQ如何保证消息的可靠性?由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
消息的发送方式有哪几种?存储消息的可靠性面临哪些挑战?消费消息的确认机制是怎样的?本文通过分析消息流转的整个过程,从消息发送、消息存储和消息消费三个阶段介绍RocketMQ是如何保证消息的可靠性的.
分布式系统中一个重要的前提假设是所有的网络传输都是不可靠的,在网络传输不可靠的情况下,保证消息的可靠传输,除了进行重试投递别无他法。常用的绝大多数消息队列RocketMQ、RabbitMQ等在消息传输上都只能保证至少传输成功一次,也即(At least once),而不能保证只传输成功一次(Exactly once)。由于分布式系统网络的不可靠,可能就会出现消息丢失的现象,那么RocketMQ是如何最大限度的保证消息不丢失的呢?那就需要从消息的产生到最终消费的整个过程来分析,消息完整链路可以划分为以下三个阶段:
一 发送端消息可靠性 。
发送端Producer发送消息Broker端的核心逻辑如下图所示:
消息发送一般有以下几种方式:同步发送、异步发送以及单向发送,业务具体选择哪种方式进行消息发送,需要根据情况进行判断,下面具体介绍不同的发送方式实现的消息可靠性保证.
1 同步发送 。
同步发送是指发送端在发送消息时,阻塞线程进行等待,直到服务器返回发送的结果。发送端如果需要保证消息的可靠性,防止消息发送失败,可以采用同步阻塞式的发送,然后同步检查Brocker返回的状态来判断消息是否持久化成功。如果发送超时或者失败,则会默认重试2次,RocketMQ选择至少传输成功一次的消息模型,但是有可能发生重复投递,因为网络传输是不可靠的,具体的重试策略可以参照第四小节.
2 异步发送 。
异步发送是指发送端在发送消息时,传入回调接口实现类,调用该发送接口后不会阻塞,发送方法会立即返回,回调任务会在另一个线程中执行,消息发送结果会回传给相应的回调函数。具体的业务实现可以根据发送的结果信息来判断是否需要重试来保证消息的可靠性.
3 单向发送 。
单向发送是指发送端发送完成之后,调用该发送接口后立刻返回,并不返回发送的结果,业务方无法根据发送的状态来判断消息是否发送成功,单向发送相对前两种发送方式来说是一种不可靠的消息发送方式,因此要保证消息发送的可靠性,不推荐采用这种方式来发送消息.
4 发送重试策略 。
RocketMQ架构模型中会有多个Borker为某个topic提供服务,一个topic下的消息分散存储在多个Broker存储端,它们是多对多关系。Broker会将其提供存储服务的topic的元数据信息上报到NameServer,对等NameServer节点组成的高可用服务会维护topic与Broker之间的映射关系,多对多的映射关系为消息可以重试发送到多个Broker端提供了前提与基础.
当发送端需要发送消息时,如果发送端中缓存了topic的路由信息,并包含了消息队列,则直接返回该路由信息,如果没有缓存或没有消息队列,则向NameServer查询该topic的路由信息,查询到路由消息之后,采用指定的队列选择策略选择相应的queue发送消息,默认是采用轮询策略,发送成功则返回, 收到异常则根据相应的策略进行重试,可以根据发送端感知到的Broker的时延、上次发送失败的Broker信息和发送端配置的是否重试不同Broker的参数以及发送端设置的最大超时时间等等策略来灵活地实现不同等级的消息发送可靠性保证。重试策略可以有效的保证消息发送成功的概率,最终提高消息发送的可靠性.
二 存储端消息可靠性 。
RocketMQ的消息存储结构如下图所示:
目前RocketMQ存储模型使用本地磁盘进行存储,数据写入为producer -> direct memory -> pagecache -> 磁盘,数据读取如果pagecache有数据则直接从pagecache读,否则需要先从磁盘加载到pagecache中。Broker存储节点的文件存储模式如下图所示:
Broker端CommitLog采用顺序写,可以大大提高写入效率,同时采用不同的刷盘模式提供不同的数据可靠性保证,此外采用了ConsumeQueue中间结构来存储偏移量信息,实现消息的分发。由于ConsumeQueue结构固定且大小有限,在实际情况中,大部分的ConsumeQueue 能够被全部读入内存,可以达到内存读取的速度。此外为了保证CommitLog和ConsumeQueue的一致性, CommitLog里存储了Consume Queues 、Message Key、Tag等所有信息,即使ConsumeQueue丢失,也可以通过 commitLog完全恢复出来,这样只要保证commitLog数据的可靠性,就可以保证Consume Queue的可靠性.
RocketMQ存储端采用本地磁盘进行CommitLog消息数据的存储,不可避免的就会带来存储可靠性的挑战,如何保证消息不丢失,RocketMQ消息服务一直在不断提高数据的可靠性.
1 存储可靠性挑战 。
RocketMQ存储端也即Broker端在存储消息的时候会面临以下的存储可靠性挑战:
1正常关闭,Broker 可以正常启动并恢复所有数据。2、3、4同步刷盘可以保证数据不丢失,异步刷盘可能导致少量数据丢失。5、6属于单点故障,且无法恢复。解决单点故障可以采用增加Slave节点,主从异步复制仍然可能有极少量数据丢失,同步复制可以完全避免单点问题.
这里一般来说就需要在性能和可靠性之间做出取舍,对于RocketMQ来说,Broker的可靠性主要由两个方面保障:
如果设置为每条消息都强制刷盘、主从复制,那么性能无疑会降低;如果不这样设置,就会有一定的可能性丢失消息。RocketMQ一般都是先把消息写到PageCache中,然后再持久化到磁盘上,数据从pagecache刷新到磁盘有两种方式,同步和异步。整体的消息写入和读取如下图所示:
针对broker端单机存储可靠性,主要依赖单机的刷盘策略,主从之间的副本复制可以参考下一章节的主从模式.
2 同步刷盘 。
消息写入内存的 PageCache后,立刻通知刷盘线程刷盘,然后等待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写成功的状态。这种方式可以保证数据绝对安全,但是吞吐量不大.
3 异步刷盘(默认) 。
消息写入到内存的 PageCache中,就立刻给客户端返回写操作成功,当 PageCache中的消息积累到一定的量时,触发一次写操作,或者定时等策略将 PageCache中的消息写入到磁盘中。这种方式吞吐量大,性能高,但是 PageCache中的数据可能丢失,不能保证数据绝对的安全.
实际应用中要结合业务场景,合理设置刷盘方式,尤其是同步刷盘的方式,由于频繁的触发磁盘写动作,会明显降低性能.
4 过期文件删除 。
由于RocketMQ操作CommitLog、ConsumeQueue文件是基于文件内存映射机制,并且在启动的时候会将所有的文件加载,为了避免内存与磁盘的浪费、能够让磁盘能够循环利用、避免因为磁盘不足导致消息无法写入等引入了文件过期删除机制。最终使得磁盘水位保持在一定水平,最终保证新写入消息的可靠存储.
三 消费端消息可靠性 。
RockerMQ默认提供了至少消费一次的消费语义来保证消息的可靠消费.
通常消费消息的确认机制一般分为两种思路:
思路1可以解决重复消费的问题但是会丢失消息,因此RocketMQ默认实现的是思路2,由各自consumer业务方保证幂等来解决重复消费问题.
消费端Consumer消费消息核心逻辑如下图所示:
1 消费重试 。
消费者从RocketMQ拉取到消息之后,需要返回消费成功来表示业务方正常消费完成。因此只有返回CONSUME_SUCCESS才算消费完成,如果返回CONSUME_LATER则会按照不同的messageDelayLevel时间进行再次消费,时间分级从秒到小时,最长时间为2个小时后再次进行消费重试,如果消费满16次之后还是未能消费成功,则不再重试,会将消息发送到死信队列,从而保证消息存储的可靠性.
2 死信队列 。
未能成功消费的消息,消息队列并不会立刻将消息丢弃,而是将消息发送到死信队列,其名称是在原队列名称前加%DLQ%,如果消息最终进入了死信队列,则可以通过RocketMQ提供的相关接口从死信队列获取到相应的消息,保证了消息消费的可靠性.
3 消息回溯 。
回溯消费是指Consumer已经消费成功的消息,或者之前消费业务逻辑有问题,现在需要重新消费。要支持此功能,则Broker存储端在向Consumer消费端投递成功消息后,消息仍然需要保留。重新消费一般是按照时间维度,例如由于Consumer系统故障,恢复后需要重新消费1小时前的数据。RocketMQ Broker提供了一种机制,可以按照时间维度来回退消费进度,这样就可以保证只要发送成功的消息,只要消息没有过期,消息始终是可以消费到的.
四 总结 。
本文从消息流转的整个过程分析了RocketMQ如何保证消息的可靠性,消息发送通过不同的重试策略保证了消息的可靠发送,消息存储通过不同的刷盘机制以及多副本来保证消息的可靠存储,消息消费通过至少消费成功一次以及消费重试机制来保证消息的可靠消费,RocketMQ在保证消息的可靠性上做到了全链路闭环,最大限度的保证了消息不丢失.
原文地址:https://zhuanlan.51cto.com/art/202102/644179.htm 。
最后此篇关于RocketMQ如何保证消息的可靠性?的文章就讲到这里了,如果你想了解更多关于RocketMQ如何保证消息的可靠性?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
01、记录器的生命周期 Serilog 大多数情况下“只需使用”,并且在创建和处理日志记录器时不需要过多考虑。然而,由于以下原因: 某些接收器(sink)涉及后台进程,特别是那些使用网络的接收器;
有在项目中使用过Java Kryonet库的 friend 愿意分享一下经验吗?我看到它被推荐过几次,但实际上没有看到任何人谈论他们使用它的经历。 具体来说,我想确保它可靠且相对稳定。或者我应该考虑使
如果我不希望用户能够访问某个页面,我需要重定向用户。例如,header('Location: ../acc/login.php'); 有多可靠?浏览器可以忽略 302 错误吗,这是正确的方法吗?提前致
我一直在使用 ZeroMQ 的请求/响应套接字来在 Web 应用程序和用于卸载处理的从属应用程序之间交换消息。我注意到在某些情况下,并不是所有发送的 ZMQ 消息都被另一方实际接收到。更奇怪的是,即使
我目前的情况是我有一个应用程序需要在新数据到达数据库表时得到通知。数据来自外部来源(我无法控制——这是唯一的集成选项)。当新数据到达时,我的应用程序需要采取某些操作——基本上是查询新数据、处理它、将结
嗨 如果lucene索引上只发生插入操作(没有删除/更新),那么docID是否真的没有改变?而且它也可靠 如果这是真的,我想用它来增量加载 FieldCache 以降低加载所有文档的开销,最好的解决方
我正在尝试使用 ActiveMQ 创建可靠的 JMS 环境。我打算采用 JDBC 主从集群方法,在这种方法中,我可以将主服务器收到的消息保存到数据库中,从服务器可以选择这些消息并运行它们,以防主服务器
我正在开发依赖于设备 UUID 的 Apache Cordova 应用程序。几个问题在我脑海中闪过,但不幸的是,我似乎无法在任何地方找到答案。 获取的 device.uuid 对于每个平台是否都相同,
这个问题是对 Intercepting/Rerouting TCP SYN packets to C++ program in linux 的(某种)跟进. 问题是:如果 SYN 或任何其他 TCP
是否存在 localIdentifier 可能会更改或不准确的情况?我正在开发一个备份照片的应用程序,我的同事告诉我不能信任 localIdentifier。然而,在做了一些研究之后,我一直无法找到任
我们的应用程序使用 APNS 来接收推送通知。然而,我们的客户声称他们的一些设备没有收到通知,并争辩说他们“必须”确保通知 100% 送达。但我读过somewhere APNS 不是 100% 可靠的
来自ZooKeeper FAQ : Reliability: A single ZooKeeper server (standalone) is essentially a coordinator w
我正在制作一个需要存储一些用户数据的 PhoneGap 应用程序。在初始应用程序启动时,将要求用户输入 URL。由于 URL 可能很长,我希望将其保存在用户的设备上,这样他就不需要在每次启动应用程序时
我是 Node.js 的新手,目前正在质疑它的可靠性。 根据我目前看到的情况,似乎存在一个重大缺陷:任何 Uncaught Error /异常都会导致服务器崩溃。当然,您可以尝试对您的代码进行防弹或将
Google PubSub 是否适合小批量(10 条消息/秒)但任务关键型消息传递,保证在任何固定时间段内及时传递每条消息? 或者,它是否更适合高吞吐量,其中个别消息可能偶尔会丢失或无限期延迟? 编辑
Erlang据报道,它已在生产系统中使用了 20 多年,正常运行时间百分比为 99.9999999%。 我做了如下数学计算: 20*365.25*24*60*60*(1 - 0.999999999)
我最近看到this SO 发布有关获取请求域的文章。我想知道此信息是否可靠(即攻击者可以“伪造”此信息吗?)。具体来说,域和请求类型(GET、POST 等)。我问的原因是因为我不确定是否可以使用它来保
谁能告诉我,当将操作发布到时间轴时,Facebook 的开放图谱 API 的可靠性如何? 背景: 我创建了一个新的 FB iOS 应用 使用自定义对象“blogpost”创建新的操作类型“write”
我正在进行 Windows Azure 试用,以评估将多个商业 ASP.NET 站点从专用托管迁移到 Azure 的情况。一切都很顺利......直到现在! 一些背景 - 站点是使用 SQL Azur
在进行代码审查时我偶然发现了 GWM在 Java-Spring-GWT Web 应用程序中。由于我不知道这个产品,我访问了它的网站,发现它的开发似乎在 2007 年停止了,因为它的最后一个稳定版本是
我是一名优秀的程序员,十分优秀!