5.3 加载快照

流程详解

流程概览

当节点重启或安装来自 Leader 的快照后,会进行加载快照来恢复状态机,其流程如下:

  1. 节点会将加载快照任务放进 ApplyTaskQueue,等待其被执行

  2. 当任务被执行时,会打开本地快照目录,并返回 SnapshotReader

  3. SnapshotReader 作为参数调用用户状态机的 on_snapshot_load

  4. 等待快照加载完成

  5. 以快照元数据中的节点配置作为参数,调用用户状态机的 on_configuration_committed

  6. 更新 applyIndex 为快照元数据中的 lastIncludedIndex

  7. 删除 logIndex<=lastIncludedIndex 的日志(细节略有出入,见以下代码解析)

  8. 将快照元数据中的节点配置设为当前节点配置

相关接口

加载快照时会调用的状态机函数:

class StateMachine {
public:
    // user defined snapshot load function
    // get and load snapshot
    // success return 0, fail return errno
    // Default: Load nothing and returns error.
    virtual int on_snapshot_load(::braft::SnapshotReader* reader);

    virtual void on_configuration_committed(const ::braft::Configuration& conf, int64_t index);
};

读取快照的 SnapshotReader

阶段一:触发加载快照

触发加载快照

节点在重启或下载完 Leader 的快照后,会触发加载快照。这两种场景都会调用 FSMCaller::on_snapshot_load 加载快照,只不过加载快照完成后的回调函数不同:

  • 重启:FirstSnapshotLoadDone

  • 安装快照:InstallSnapshotDone

场景 1:节点重启

节点重启时会遍历快照存储目录,获取最新的快照目录,将其打开并返回 SnapshotReader,然后调用 FSMCaller::on_snapshot_load 加载快照,并同步等待其加载完成:

场景 2:安装快照

当节点下载完 Leader 的快照时,会调用 load_downloading_snapshot 加载快照。关于安装快照相关流程,可以参考<5.2 安装快照>

任务入队执行

on_snapshot_load 会将加载快照任务放入 ApplyTaskQueue,等待其被执行:

队列消费函数会调用 FSMCaller::do_snapshot_load 执行加载快照任务:

FSMCaller::do_snapshot_load 是加载快照的主干函数,在该函数中主要做以下几件事,而每一件事我们将在下面详细介绍:

阶段二:用户加载快照

on_snapshot_load

用户需要实现状态机的 on_snapshot_load 函数来加载快照:

get_path

get_path 接口会返回快照目录的绝对路径,所有快照的文件集都位于该目录下:

load_meta

load_meta 接口会将快照元数据返回给用户:

list_files

list_files 接口会从快照元数据中返回当前快照中所有文件的相对路径:

阶段三:完成快照加载

on_configuration_committed

在上面的 FSMCaller::do_snapshot_load 函数中,我们提到过,在快照加载完成后,会调用用户状态机的 on_configuration_committed 函数:

更新 applyIndex

同样是在 FSMCaller::do_snapshot_load 函数中,在快照加载完成后,会设置 applyIndex 为快照元数据中的 lastIncludedIndex

调用 Closure

我们上面提到了,对于节点重启和安装快照这两种不同的加载快照场景,会设置不同的回调函数,但是其最终都会调用 SnapshotExecutor::on_snapshot_load_done 来做收尾工作:

on_snapshot_load_done 会做以下几件事:

删除日志

set_snapshot 主要执行以下 2 件事:

  • 将快照元数据中的节点配置保存至 _config_manager

  • 根据快照元数据中的 lastIncludeIndex 删除相应的日志

设置节点配置

将快照元数据中的节点配置设置为当前节点配置。快照中的节点配置我们已经在 LogManager::set_snapshot 将其保存在 _config_manager 中了:

Last updated