如何启用 Khepri
从 RabbitMQ 4.0 开始,Mnesia 仍然是默认的元数据存储后端。Khepri 必须使用 khepri_db
功能标志显式启用。
本页演示了如何在各种情况下启用 Khepri 以及用户应注意的事项。
虽然 Khepri 在 RabbitMQ 4.0.x 中得到完全支持,但它没有 Mnesia 17 年的广泛使用经验。我们鼓励所有 RabbitMQ 用户在生产环境中采用 Khepri 之前进行彻底测试。
从启用 Khepri 的 4.0.x 版本升级到未来版本是可能的。
术语表
功能标志子系统使用稳定和实验性这两个词来限定功能标志的成熟度。
实验性功能标志用于两种情况
- 为了引入更改,以便在开发早期获得反馈。这些更改可能会被撤销,升级启用了此类功能标志的 RabbitMQ 节点可能不可行,并且可能不提供支持。
- 对于 RabbitMQ 团队承诺并提供支持的功能,直到它准备好默认启用,并可能取代旧系统。
RabbitMQ 3.13.x 中的 Khepri 属于第一组。请放心,RabbitMQ 4.0 及更高版本中的 Khepri 属于第二组,因此得到完全支持。
在全新的 RabbitMQ 节点上
使用命令行界面
-
使用您选择的方法启动新的 RabbitMQ 节点。下面的示例直接执行
rabbitmq-server(8)
命令- bash
- PowerShell
rabbitmq-server
rabbitmq-server.bat
此时,节点正在使用 Mnesia 作为元数据存储后端。
-
启用
khepri_db
功能标志- bash
- PowerShell
# Opt-in to enable Khepri.
rabbitmqctl enable_feature_flag --experimental khepri_db# Opt-in to enable Khepri.
rabbitmqctl.bat enable_feature_flag --experimental khepri_db
请参阅下一页,了解更多关于 Mnesia 节点和 Khepri 节点集群在一起时会发生什么。
使用管理界面
-
使用您选择的方法启动新的 RabbitMQ 节点。请参阅上面的示例。
此时,节点正在使用 Mnesia 作为元数据存储后端。
-
启用 管理插件
- bash
- PowerShell
rabbitmq-plugins enable rabbitmq_management
rabbitmq-plugins.bat enable rabbitmq_management
-
打开并登录到管理界面。
-
导航到“Admin > Feature Flags”。
-
勾选“我了解风险”并单击“启用”按钮
管理界面中的实验性功能标志部分
使用环境变量
$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,就像任何其他功能标志一样。当节点或整个集群停止时,无法启用 Khepri。
要启用 Khepri,请使用命令行界面命令或上面描述的管理界面方法。
从 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 存储中的记录数
- 节点正常运行时间
- 节点名称
因此,如果在某些节点已经以 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 的活动。