如何启用 Khepri
从 RabbitMQ 4.0 开始,Mnesia 仍然是默认的元数据存储后端。必须使用 khepri_db
特性标志 显式启用 Khepri。
本页演示了如何在各种情况下启用 Khepri 以及用户需要注意的事项。
虽然 Khepri 在 RabbitMQ 4.0.x 中得到完全支持,但它没有像 Mnesia 那样拥有 17 年的广泛使用经验。我们鼓励所有 RabbitMQ 用户在生产环境中采用 Khepri 之前对其进行彻底测试。
可以从 4.0.x 升级到启用 Khepri 的未来版本。
术语
特性标志 子系统使用“稳定”和“实验性”这两个词来描述特性标志的成熟度。
实验性特性标志在两种情况下使用
- 在开发过程中引入更改以尽早获得反馈。这些更改可能会被撤销,升级启用了此类特性标志的 RabbitMQ 节点可能不可行,并且可能无法提供支持。
- 对于 RabbitMQ 团队承诺并提供支持的特性,直到它准备好默认启用,可能取代旧系统为止。
RabbitMQ 3.13.x 中的 Khepri 属于第一组。请放心,RabbitMQ 4.0 及更高版本中的 Khepri 属于第二组,因此得到完全支持。
在全新 RabbitMQ 节点上
使用 CLI
-
使用您选择的任何方法启动新的 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 的节点一起集群时会发生的情况。
使用管理 UI
-
使用您选择的任何方法启动新的 RabbitMQ 节点。请参阅 上面的示例。
此时,节点使用 Mnesia 作为元数据存储后端。
-
启用 管理插件
- bash
- PowerShell
rabbitmq-plugins enable rabbitmq_management
rabbitmq-plugins.bat enable rabbitmq_management
-
打开并登录到 管理 UI。
-
导航到“管理 > 特性标志”。
-
勾选“我了解风险”并点击“启用”按钮
使用环境变量
$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,请使用上面介绍的 CLI 命令 或 管理 UI 方法。
从 Mnesia 迁移到 Khepri 的过程与 RabbitMQ 的常规活动并行进行。但是,此迁移会占用资源,并且会在过程结束时暂停其他活动一小段时间。因此,请在非高峰负载时执行此迁移。
启用 Khepri 后会发生什么?
从 Mnesia 迁移到 Khepri 是由 khepri_mnesia_migration
库 负责的。
此库分两个阶段执行迁移
- 它将集群成员资格从 Mnesia 同步到 Khepri。
- 它将记录从 Mnesia 表复制到 Khepri 存储。
步骤 1:集群成员资格同步
常见的情况是,Khepri 在基于 Mnesia 的集群中启用,因此所有参与的节点都是从 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 进行活动。