RocketMQ源码分析(十五)之文件恢复

版本

  1. 基于rocketmq-all-4.3.1版本

异常分析

  1. 由于ConsumeQueue和Index文件都是根据CommitLog文件异步构建的,所以ConsumeQueue、Index与CommitLog文件的数据就是最终一致,而不是强一致的。这样在Broker重启时就可能出现不一致性的情况

    • CommitLog文件同步刷盘,当准备转发给ConsumeQueue文件时突然断电或者出现故障,导致ConsumeQueue存储失败
    • 在刷盘时,由于突然断电,只写入一部分数据到磁盘CommitLog文件中
    • 当数据写入CommitLog文件后才会将刷盘点记录到检查点中,有可能刷盘完成,但是写入检查点文件并没有完成
  2. RocketMQ 有两种文件恢复机制。判断异常的方式是在 broker启动的时候创建一个 abort 空文件,在正常结束的时候删掉这个文件。在下一次启动 broker 时,如果发现了 abort 文件,则认为是异常宕机,否则就是正常关机。

    • 正常关机恢复:先从倒数第三个文件开始进行恢复,然后按照消息的存储格式进行查找,如果改文件中所有的消息都符合消息存储格式,则继续查找下一个文件,直到找到最后一条消息所在的位置
    • 异常宕机恢复:异常停止刷盘时,从最后一个文件开始查找,在查找时读取改文件第一条消息的存储时间,如果这个存储时间小于检查点文件中的刷盘时间,就可以从这个文件开始恢复,如果这个文件中第一条消息的存储时间大于检查点,说明不能从这个文件开始恢复,需要寻找上一个文件。因为检查点文件中的刷盘点代表的是100%可靠的消息。
  3. 关机恢复机制设计的目的就是保证数据0丢失,RocketMQ通过abort和checkpoint来保证数据0丢失

    • abort文件:abort文件时一个空文件,在Broker启动时会被创建,当正常关闭的时候会被删除。如果Broker是异常关闭,则不会删除此文件
    • checkpoint文件:是一个检查点文件,此文件保存了Broker最后一次正常存储数据的时间,当重启Broker时,恢复程序可以从此文件获取应该从哪个时刻开始恢复数据
  4. 当索引文件刷盘成功,消息队列消费文件未刷盘成功且宕机时,会造成消息消费队列文件丢失的问题。但只要 Commitlog 文件没有丢失,就可以利用 RocketMQ 的文件恢复机制,恢复丢失的消息消费队列文件。在 RocketMQ 的文件恢复机制中,有针对异常宕机进行文件恢复的机制。当 broker 异常启动,在文件恢复过程中,RocketMQ 会将最后一个有效文件的所有消息转发到消息消费队列和索引文件,确保不丢失消息,但同时也会带来重复消费的问题,RocketMQ 保证消息不丢失但不保证消息不会重复消费,故消息消费业务方需要实现消息消费的幂等设计。

StoreCheckpoint

  1. StoreCheckpoint(检查点)主要用于记录CommitLogConsumeQueueIndex文件的刷盘时间点,当上一次broker是异常结束时,会根据StoreCheckpoint的数据进行恢复。checkpoint(检查点)文件固定长度为4KB
    在这里插入图片描述

  2. 当索引文件刷盘成功,消息队列消费文件未刷盘成功且宕机时,会造成消息消费队列文件丢失的问题。但只要 Commitlog 文件没有丢失,就可以利用 RocketMQ 的文件恢复机制,恢复丢失的消息消费队列文件。在 RocketMQ 的文件恢复机制中,有针对异常宕机进行文件恢复的机制。当 broker 异常启动,在文件恢复过程中,RocketMQ 会将最后一个有效文件的所有消息转发到消息消费队列和索引文件,确保不丢失消息,但同时也会带来重复消费的问题,RocketMQ 保证消息不丢失但不保证消息不会重复消费,故消息消费业务方需要实现消息消费的幂等设计。

  3. StoreCheckpoint文件源码

    public class StoreCheckpoint {
         
        private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.STORE_LOGGER_NAME);
        private final RandomAccessFile randomAccessFile;
        private final FileChannel fileChannel;
        private final MappedByteBuffer mappedByteBuffer;
        //CommitLog最新一条记录的存储时间
        private volatile long physicMsgTimestamp = 0;
        //ConsumeQueue最新一条记录的存储时间
        private volatile long logicsMsgTimestamp = 0;
        //Index File最新一条记录的存储时间
        private volatile long indexMsgTimestamp = 0;
    
        public StoreCheckpoint(final String scpPath) throws IOException {
         
            File file = new File(scpPath);
            MappedFile.ensureDirOK(file.getParent());
            boolean fileExists = file.exists();
    
            this.randomAccessFile = new RandomAccessFile(file, "rw");
            //一旦建立映射(map),fileChannel其实就可以关闭了,关闭fileChannel对映射不会有影响
            //TODO 所以这个地方的fileChannel是不是直接关闭就好?
            this.fileChannel = this.randomAccessFile.getChannel();
            this.mappedByteBuffer = fileChannel.map(MapMode.READ_WRITE, 0, MappedFile.OS_PAGE_SIZE);
    
            if (fileExists) {
         
                log.info("store checkpoint file exists, " + scpPath);
                this.physicMsgTimestamp = this.mappedByteBuffer.getLong(0);
                this.logicsMsgTimestamp = this.mappedByteBuffer.getLong(8);
                this.indexMsgTimestamp = this.mappedByteBuffer.getLong(16);
    
                log.info("store checkpoint file physicMsgTimestamp " + this.physicMsgTimestamp + ", "
                    + UtilAll.timeMillisToHumanString(this.physicMsgTimestamp));
                log.info("store checkpoint file logicsMsgTimestamp " + this.logicsMsgTimestamp + ", "
                    + UtilAll.timeMillisToHumanString(this.logicsMsgTimestamp));
                log.info("store checkpoint file indexMsgTimestamp " + this.indexMsgTimestamp + ", "
                    + UtilAll.timeMillisToHumanString(this.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值