如何启用 Khepri
从 RabbitMQ 4.2.0 版本开始,Khepri 成为所有新部署的默认元数据存储后端。对于最初使用 RabbitMQ 4.1.x 或更早版本的现有部署,必须使用 khepri_db 功能标志(feature flag)显式启用 Khepri。
本页面演示了在各种情况下如何启用 Khepri,以及用户需要注意的事项。
在全新的 RabbitMQ 节点上
使用 CLI
-
选择一种方法启动新的 RabbitMQ 节点。下面的示例直接执行了
rabbitmq-server(8)命令- bash
- PowerShell
rabbitmq-serverrabbitmq-server.bat此时,该节点正在使用 Mnesia 作为元数据存储后端。
-
启用
khepri_db功能标志- bash
- PowerShell
# Opt-in to enable Khepri.rabbitmqctl enable_feature_flag khepri_db# Opt-in to enable Khepri.rabbitmqctl.bat enable_feature_flag khepri_db
请参阅下一页,了解当 Mnesia 节点和 Khepri 节点组成集群时会发生什么。
使用管理 UI
-
选择一种方法启动新的 RabbitMQ 节点。参见上面的示例。
此时,该节点正在使用 Mnesia 作为元数据存储后端。
-
- bash
- PowerShell
rabbitmq-plugins enable rabbitmq_managementrabbitmq-plugins.bat enable rabbitmq_management -
打开并登录 管理界面(management UI)。
-
导航至 “Admin > Feature Flags”(管理 > 功能标志)。
-
启用
khepri_db。
使用环境变量
$RABBITMQ_FEATURE_FLAGS 环境变量可以设置为在新节点引导时启用功能的完整列表,或者相对于默认启用功能列表的相对列表。此变量仅在首次引导时考虑;之后将被忽略。
选择一种方法启动新的 RabbitMQ 节点,并在过程中设置 $RABBITMQ_FEATURE_FLAGS 变量。下面的示例直接执行了 rabbitmq-server(8) 命令
- bash
- PowerShell
env RABBITMQ_FEATURE_FLAGS="+khepri_db" rabbitmq-server
$Env:RABBITMQ_FEATURE_FLAGS = '+khepri_db'
rabbitmq-server.bat
RabbitMQ 节点将从一开始就使用 Khepri。
在现有的独立节点或集群上
和任何其他功能标志一样,Khepri 可以在所有集群节点在线且集群状态健康(healthy)时启用。当节点或整个集群停止时,无法启用 Khepri。
要启用 Khepri,请使用上述命令行(CLI)或管理界面方法。
现有数据从 Mnesia 到 Khepri 的迁移与 RabbitMQ 的常规活动并行运行。但是,此迁移会占用资源,并会在过程接近结束时暂停其他活动一小段时间。因此,请避开高峰负载时段进行此迁移。
启用 Khepri 后会发生什么?
从 Mnesia 到 Khepri 的迁移由 khepri_mnesia_migration 库负责。
该库分两个阶段执行迁移
- 它将集群成员关系从 Mnesia 同步到 Khepri。
- 它将记录从 Mnesia 表复制到 Khepri 存储中。
第 1 步:集群成员关系同步
常见的情况是在基于 Mnesia 的集群中启用 Khepri,因此从 Khepri 的角度来看,所有相关节点都是孤立的单节点。
为了更加安全并避免某些节点已经在 Khepri 层面组建了集群而导致数据丢失,khepri_mnesia_migration 使用了多个条件来确保 Khepri 集群的确定性。为此,它遵循以下步骤
-
查询 Mnesia 集群的成员列表。这是我们希望在 Khepri 中组建集群的基础节点列表。
-
查询每个节点以获取 Khepri 集群的成员。通常,Khepri 尚未组建集群,因此每个节点只返回自身。
-
根据以下标准对 Khepri “集群”列表进行排序
- 集群规模(即成员数量)
- Khepri 存储中的记录数量
- 节点正常运行时间(uptime)
- 节点名称
因此,如果某些节点已经在 Khepri 层面组建了集群,Khepri 集群将按最大集群(节点集)优先排序。
但通常情况下,节点将是未组建集群的,因此按节点正常运行时间和名称排序。
-
它选择根据上述标准筛选出的最大的 Khepri “集群”,并将所有其他节点添加到该最大集群中
-
如果某些节点已在 Khepri 层面组建了集群但不在 Mnesia 中,它们将从 Khepri 中移除
第 2 步:模式记录复制
一旦 Mnesia 和 Khepri 之间的集群成员视图一致,khepri_mnesia_migration 就可以继续进行实际的数据迁移。它在执行复制的同时,允许在 Mnesia 中进行写入,直到最后一刻。
复制依赖于 RabbitMQ 提供的回调模块。这些回调模块负责告诉 khepri_mnesia_migration 表 $table 中的记录 $record 应该进入 Khepri 路径 $path(可能在进行一些记录转换之后)。
以下是数据复制算法的步骤
-
khepri_mnesia_migration将迁移标记为 Khepri 中的进行中状态。 -
它订阅所有 Mnesia 更新。
-
它使用 Mnesia 备份与恢复 API 进行从 Mnesia 到 Khepri 的首次复制。这是基于 Mnesia 中的时间检查点,因此视图是一致的。
-
它将所有 Mnesia 表标记为只读。这是 RabbitMQ 活动被暂停的地方。客户端操作可能会因此超时。
-
现在消费在第 2 步中通过 Mnesia 订阅收到的所有更新,并写入 Khepri。由于表是只读的,可以确保更新流最终会结束。
-
它将迁移标记为完成。RabbitMQ 可以恢复活动:从现在开始,它们将使用 Khepri。
-
它继续进行清理:表被删除。
出错时的回滚
如果在此过程中发生错误,一切都会回滚,RabbitMQ 将像以前一样使用 Mnesia 恢复活动。