把RocketMQ的文件过期删除机制弄明白了,至少可以拯救一半的头发

本文详细探讨了RocketMQ的文件过期删除机制,包括凌晨4点的定时删除、磁盘空间不足时的删除和人工触发的删除。同时,介绍了文件恢复机制,从启动时的检查到数据的有效性校验,确保系统的稳定运行。
摘要由CSDN通过智能技术生成

大家好!

今天聊一下RocketMQ的文件过期删除机制

本章概括

源码定位

Broker是RocketMQ的核心,提供了消息的接收,存储,拉取等功能

我们可以先从Broker服务入手。从源码可以得知。RocketMQ启用了一个 BrokerController 的 start 函数

public static void main(String[] args) {
    start(createBrokerController(args));
}

public static BrokerController start(BrokerController controller) {
    try {
        controller.start();

        String tip = "The broker[";
        if (null != controller.getBrokerConfig().getNamesrvAddr()) {
            // 日志拼接
        }

        log.info(tip);
        System.out.printf("%s%n", tip);
        return controller;
    } catch (Throwable e) {
        e.printStackTrace();
        System.exit(-1);
    }

    return null;
}
复制代码

下列是start 函数启动的异步线程,他启动了一个 messageStore

public void start() throws Exception {
        if (this.messageStore != null) {
            this.messageStore.start();
        }
    }
复制代码

从 messageStore.start() 函数进入后会有一个消息存储的第三方接口。

public interface MessageStore {

    /**
     * Load previously stored messages.
     *
     * @return true if success; false otherwise.
     */
    boolean load();

    /**
     * Launch this message store.
     *
     * @throws Exception if there is any error.
     */
    void start() throws Exception;
}

复制代码

继续围绕 start 函数展开实现类查找,可以看到最终由 DefaultMessageStore 实现类实现

定位到具体问题之后,可以看到 start 调用了一个 addScheduleTask 函数

这个函数主要处理的就是清除过期日志服务。

 public void start() throws Exception {
     //刷新ConsumeQueue的服务启动
     this.flushConsumeQueueService.start();
     //CommitLog刷新的服务启动
     this.commitLog.start();
     //存储状态检测的服务启动
     this.storeStatsService.start();

     //创建临时文件,来表示是否正常关机
     this.createTempFile();
     //启动其他服务。比如清除过期日志的服务等
     this.addScheduleTask();
     this.shutdown = false;
 }
复制代码

这篇文件聊的就是这个 addScheduleTask 函数。言归正传,步入正题!

流程图

过期删除机制

文件过期删除

首次执行时间是60000毫秒=60秒。其余间隔执行都是每10秒执行一次删除。

// 资源回收间隔
private int cleanResourceInterval = 10000;
/**
  * {}要执行的任务
  * 1.延迟第一次执行的时间
  * 2.两次执行之间的时间 10000 资源回收间隔
  * 3.毫秒
*/
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
       @Override
       public void run() {
             DefaultMessageStore.this.cleanFilesPeriodically();
       }
// 延迟第一次执行的时间
}, 1000 * 60, this.messageStoreConfig.getCleanResourceInterval(), TimeUnit.MILLISECONDS);
复制代码

对于删除过期的时机包括以下3种:

  1. 默认凌晨4点。这个也比较好理解,这个时候用的人也比较少,删除对系统的影响就降到最小。
  2. 磁盘空间不足。当磁盘空间不足的时候,就要删除过期文件以提供更多的空间出来接收消息。
  3. 人工触发,指人为的介入去删除。

删除的文件是过期文件,那哪些文件是过期的呢?

首先是保留时间,默认72小时,也就是3天,超过3天的数据,是需要删除的。

deleteExpiredFiles 是用于删除过期文件。执行步骤如下:

  1. 首先是需要判断是否需要删除文件,通过两个方法的调用isTimeToDelete和isSpaceToDelete判断是否达到定时删除时间以及是否磁盘已满需要删除,以及判断属性DefaultMessageStore.CleanCommitLogService#manualDeleteFileSeveralTimes是否大于0意味着需要手动删除。如果这三个条件任意为真,意味着需要执行删除,那就继续后续的流程。否则结束当前方法。
  2. 如果是手动删除,则属性DefaultMessageStore.CleanCommitLogService#manualDeleteFileSeveralTimes减1.
  3. 如果属性MessageStoreConfig#cleanFileForciblyEnable和DefaultMessageStore.CleanCommitLogService#cleanImmediately为真,声明cleanAtOnece为true,否则为false。
  4. 调用方法 CommitLog#deleteExpiredFile 进行文件删除。方法需要4个入参,分别是: expiredTime:过期时间或者说文件删除前的保留时间,默认为72小时。 deleteFilesInterval:文件删除间隔,这里取值为100. intervalForcibly:该参数用于强制文件强制释放时间间隔,单位是毫秒。这里取值为120*1000, cleanImmediately:是否立即执行删除,这边使用的就是步骤3中的数据。
/**
 * 删除已经失效的
 */
private void deleteExpiredFiles() {
    int deleteCount = 0;
    // 文件保留时长 72
    long fileReservedTime = DefaultMessageStore.this.getMessageStoreConfig().getFileReservedTime();
    // 100
    int deletePhysicFilesInterval = DefaultMessageStore.this.getMessageStoreConfig().getDeleteCommitLogFilesInterval();
    // 1000 * 120 = 120000毫秒 = 120秒
    int destroyMapedFileIntervalForcibly = DefaultMessageStore.this.getMessageStoreConfig().getDestroyMapedFileIntervalForcibly();
    // 判断有没到凌晨4点
    boolean timeup = this.isTimeToDelete();
    // 空间是否上限
    boolean spacefull = this.isSpaceToDelete();
    // 手动删除  经过20次的调度
    boolean manualDelete = this.manualDeleteFileSeveralTimes > 0;

    if (timeup || spacefull || manualDelete) {
        if (manualDelete)
            this.manualDeleteFileSeveralTimes--;

        boolean cleanAtOnce = DefaultMessageStore.this.ge
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值