引言

RocketMq 作为一个成熟的消息中间件,自身保证了高可用性。学习RocketMq中的高可用性可以帮助我们自己在平时编写代码时能够编写处高可用的代码。


对于RocketMq,高可用主要在这四块进行保证

  • 消息发送的高可用:在消息发送时可能会遇到网络问题、Broker 宕机等情况导致消息没有发送成功
  • 消息存储的高可用:在 RocketMQ 中消息存储时Broker发生故障导致消息没有保存下来
  • 消息消费的高可用:可能由于网络原因导致,也可能由于业务逻辑错误导致消息一直消费失败
  • 集群管理的高可用:整一个生产者,broker,消费者的整体能够高可用,主要NameServer的高可用性如何保证

对于这四点,我们依次来学习一下RocketMq中是如何保证的。这一篇主要将 RocketMq 是如何做到存储高可用性的。

1、消息存储的高可用

在机器上的内存中,数据是不安全的,因为机器在断电后这些在内存中的数据就会全部丢失,那么我们保证消息能够不丢失,就需要对这些数据进行持久化到硬盘。

但是在恶劣环境下,可能机器都损坏了,例如火灾了,导致这些机器上的硬盘都损坏了。这样该如何处理呢?处理方式就是主从同步,可以这样说,实现了这两种方式,除非发生第三次世界大战,一般是不会造成数据丢失了。

1.1、RocketMq 数据持久化
1.1.1、数据是何时进行持久化的

org.apache.rocketmq.remoting.netty.NettyRemotingAbstract#processRequestCommand

上面的方法在 RocketMq 启动后就开启了,用来接收客户端发来的请求,包括生产者"发送消息"的请求。

在找到方法后就会由对应的方法来处理,其中

而这个pair.getObject1获取得到的处理方式是否是AsyncNettyRequestProcessor实现,这里接收生产者 “消息发送” 的请求时异步的,所以会调用asyncProcessRequest方法。再处理后进入到SendMessageProcessor流程中

org.apache.rocketmq.broker.processor.SendMessageProcessor#asyncProcessRequest

org.apache.rocketmq.broker.processor.SendMessageProcessor#asyncSendMessage

org.apache.rocketmq.store.DefaultMessageStore#asyncPutMessage

org.apache.rocketmq.store.CommitLog#asyncPutMessage

将消息同步到消息内存中

启动刷盘操作和同步操作

我们可以总结一下:消息的持久化是在接收到生产者发来的消息后就会触发的。在数据同步到mappedFile中后,系统就准备好了和commitLog一一对应的数据体,接下来就是进行数据刷盘和数据主从同步这两项操作,也正式这两项操作,保证了消息的高可用性。

1.1.2、数据是如何进行持久化的

在上面最后通过submitFlushRequest方法来异步唤醒刷盘操作,那么我们来一起看下这个函数

org.apache.rocketmq.store.CommitLog#submitFlushRequest


可以看到刷盘主要有三种

那具体的刷盘方式这里就不在具体展开了,主要聚集在两个类中mappedFileQueuemappedFile

其中mappedFileQueue对外统一处理类,其在flush时首先会选出对应的MappedFile,上面说过这个对象中就会存储具体的消息数据,然后MappedFile就会将对应的数据持久化到对应的commitLog文件上。

对于MappedFileQueue而言,其记录了两个属性:flushedWherecommittedWhere。前者代表着目前已经落盘的偏移量。后者代表已经提交到文件的偏移量。显然,后者这个属性只有在异步加速模式下才会使用到(也就是开启了transientStorePoolEnable)。

对于MappedFile而言,有三个属性:wrotePositioncommittedPositionflushedPosition。代表含义如下

  • wrotePosition:已经写入的内容的偏移量。这个偏移量可能是写入到文件也可能是写入到内存。
  • committedPosition:内存区域提交到文件的偏移量。该属性只有在异步加速模式下才会有用。
  • flushedPosition:已经刷入磁盘的偏移量。
1.2、RocketMq 数据主从同步

broker启动时就会开启接收从服务连接的请求,发生的地点为HAService类上

org.apache.rocketmq.store.ha.HAService#start


这里简单介绍一下这几个类的作用

  • AcceptSocketService:职责初始化TCP通道,监听新的连接并创建HAConnection。
  • GroupTransferService:职责判断主从同步是否完成,完成后唤醒消息发送线程。
  • HAClient:是Slave封装实现类,负责与Master建立连接通道,并从通道中获取数据存储;并向Master上报Slave存储的最大物理偏移量。

所以在AcceptSocketService启动后就开启了监听,等待从服务来进行连接,RocketMq中的试下如下

org.apache.rocketmq.store.ha.HAService.AcceptSocketService#run


上面的HAConnection#start()便是唤醒了WriteSocketServiceReadSocketService这两个服务来控制服务的socket读写。
这里先来看下WriteSocketService,这个函数有点长,我们分段来分析

org.apache.rocketmq.store.ha.HAConnection.WriteSocketService#run


这里计算下一次同步数据的偏移量的方式是获取最新的MappedFile的初始偏移量,所以我们可以知道当如果有新的从服务器和主服务器建立连接后,数据同步时从最新的MappedFile文件开始同步的,并不是全部的数据都进行同步。接下来的程序是

最后就是数据的传输了

下面便是write事件的流程

从broker服务器的读事件同理,在等待主服务器写的信息到来后,就将其首先写入自己的内存中,然后根据配置来同步或者异步刷盘。

不知道大家还记得上面在生产者发送一条消息时,最终触发了两个方法

其中submitFlushRequest方法是用来唤醒刷盘操作的,那么这个submitReplicaaRequest方法看命名就知道是用来触发主从同步的,但是我们通过上面的分析,可以知道,是主broker服务开启监听,等待从broker服务器发来需要同步数据的请求,然后主broker根据从broker发过来的数据同步起点(如果第一次同步,则不需要,这时候主broker服务是同步的最新的CommitLog文件),将最新的数据同步给从broker。好像不需要这里进行触发呀?带着这个问题我们来一起看下这个方法中具体做了什么。

org.apache.rocketmq.store.CommitLog#submitReplicaRequest


我们可以知道,这个函数主要是作用于消息保证高安全性的情况。在这种情况下,在返回给生产者消息已经发送成功前,必须要保证消息已经持久化,并且在有主从时还需要保证消息已经主从同步了。这个wakeupAll能用来立即唤醒等待的线程,不然线程可能正在处于wait(100)的场景下,用了这个能够加快同步速度。

那么还有最后一个问题,就是从broker服务器是如何发起数据同不请求的呢?

org.apache.rocketmq.broker.BrokerController#handleSlaveSynchronize


答案就在这个函数上,在broker启动时就会判断当前的broker是否是slave,如果是的话,就会开启一个定时任务,间隔是10s,会不间断的向主broker服务器请求同步数据。

RocketMq 高可用性解析(一)存储高可用相关推荐

  1. 守得云开见月明:一次ASM存储高可用故障解决过程分析

    关注我们获得更多内容 作者 | 姜劲松,云和恩墨专家支持部Oracle技术专家,Oracle OCP,MySQL OCP,RHCE等认证专家.长期服务移动运营商行业客户,精通 oracle 性能优化, ...

  2. Linux: CentOS 7下搭建高可用集群

    转载: http://linux.cn/article-3963-1.html 本文以两台机器实现双集热备高可用集群,主机名node1的IP为192.168.122.168 ,主机名node2的IP为 ...

  3. 高可用 Redis 服务架构分析与搭建

    基于内存的Redis应该是目前各种web开发业务中最为常用的key-value数据库了,我们经常在业务中用其存储用户登陆态(Session存储),加速一些热数据的查询(相比较mysql而言,速度有数量 ...

  4. 如何搭建高可用Redis服务

    作者:漫步CODE人生 来自:cnblogs.com/scode2/p/8670980.html 题记 基于内存的Redis应该是目前各种web开发业务中最为常用的key-value数据库了,我们经常 ...

  5. 实现基于Keepalived主从高可用集群网站架构

    背景 上一期我们实现了基于lvs负载均衡集群的电商网站架构,随着业务的发展,网站的访问量越来越大,网站访问量已经从原来的1000QPS,变为3000QPS,目前业务已经通过集群LVS架构可做到随时拓展 ...

  6. 教你用 3 台机器搞定一个 Redis 高可用架构

    转载自   教你用 3 台机器搞定一个 Redis 高可用架构 基于内存的 Redis 应该是目前各种 Web 开发业务中最为常用的 key-value 数据库了. 我们经常在业务中用其存储用户登陆态 ...

  7. 高可用Redis服务架构分析与搭建

    作者:HorstXu 原文:https://www.cnblogs.com/xuning/p/8464625.html 基于内存的Redis应该是目前各种Web开发业务中最为常用的Key-Value数 ...

  8. php redis 投票_高可用Redis服务架构分析与搭建

    HorstXuhttps://www.cnblogs.com/xuning/p/8464625.html 基于内存的Redis应该是目前各种web开发业务中最为常用的key-value数据库了,我们经 ...

  9. 一步一步打造MySQL高可用平台

    六月 北京 | 高性能计算之GPU CUDA培训 6月22-24日三天密集式学习  快速带你入门阅读全文> 正文共3592个字,4图,预计阅读时间18分钟. 引子 笔者刚开始进入公司的时候,主要 ...

最新文章

  1. 我的.net程序为何不能执行?
  2. 1030 完美数列(two pointers解法)
  3. MapReduce的统计和排序功能
  4. gentoo.tw的临时解决方法[转贴]
  5. Dapr 在阿里云原生的实践
  6. 【STM32】error unknown register name vfpcc in asm的解决方法
  7. 优美的Fibonacci数列与矩阵
  8. 本地环境和测试环境搭建
  9. C#LeetCode刷题之#414-第三大的数(Third Maximum Number)
  10. ​腾讯第一季度员工平均月薪 7.6 万元;“淘宝特价版”App 正式更名为“淘特”;Deno 1.10 正式发布|极客头条...
  11. UE4官网关于GamePlay框架的介绍
  12. 八大排序算法的时间、空间复杂度和稳定性
  13. 网易云MUSIC年终奖0.5?听到消息我扔了耳机
  14. 服务器上线运行正常但不能上网,网线是好的,插笔记本正常上网,插在服务器上却不能上网的解决方法...
  15. 润乾报表数据集中参数和宏的使用方法
  16. Arduino使用手指测心跳模块
  17. 特斯拉自家电池厂浮出水面!占地18万平米,就在加州超级工厂隔壁
  18. microbit c语言编程软件,Micro:bit图形化编程实现计算器
  19. ue4 改变枢轴位置_UE4虚幻引擎学习云笔记(五)-静态网格体编辑器
  20. 基于HTML+CSS+JavaScript仿瓜子二手车官网【学生网页设计作业源码】

热门文章

  1. android novate乱码,Android信任指定CA證書+Okhttp+限定https
  2. 三菱PLC通讯错误号列表及原因
  3. CNCF里程碑:超过375家会员
  4. 20201222 Python基本数据类型
  5. 判断一个年份是不是闰年(Java)
  6. 软件测试基础(三)测试环境与框架
  7. android 代码设置tint,Android Tint 使用
  8. iOS 九宫格,HUD,定时任务
  9. 推荐大家6本Python入门书籍
  10. seo伪原创工具(解析新云查新型伪原创模式工具)