NARIX 是使用 Rust 编写、以超高性能为目标的 RESP2/RESP3 前置代理与托管复制 HA 控制面,同时提供面向开发和运维的 readonly 查询入口。它支持多种 KV 后端及五种代理模式,业务客户端通过稳定地址接入,由 NARIX 处理连接、路由、认证和访问策略。
Dragonfly HA 是 NARIX 最突出的特色模式。 它在 Dragonfly 原生主从复制之上提供完整的 HA 控制面,持续管理故障探测、受控切主、安全路由、副本拓扑与持久化责任。业务保留普通 Redis 客户端连接方式,无需接入专用 SDK。
围绕 Dragonfly HA,NARIX 持续管理五件事:
- 安全切主:确认主节点故障后先保护路由,再经过 fencing、复制证据和动作权威门禁提升候选。
- 稳定入口:切主或保护时关闭旧主连接;客户端重连后进入已确认的新主,控制面无需进入每条命令的转发路径。
- 拓扑收敛:副本直接跟随当前主节点;级联、错误上游和多主证据触发保护与受控恢复。
- 持久化分工:多节点稳态由副本承担快照;合格副本充足时分离无快照热备与快照节点,交接先验证新责任再撤下旧责任。
- 多实例协同:通过租约或内置协调集群串行化控制动作,并以事务方式发布配置。
Dragonfly HA 的普通读写采用一对一透明数据通道,控制探测与业务转发分离;实际吞吐和额外延迟见性能数据。HA 不等于零数据丢失:Dragonfly 的异步复制仍有 RPO 窗口,默认软隔离也不能保证旧主失去写能力;生产强隔离需要可靠的外部 fencing。
除 Dragonfly 外,托管复制 HA 还适配 Redis、Valkey、Redict、KeyDB 和 Kvrocks;standalone、Sentinel、Cluster 单入口与节点代理模式分别服务固定后端、动态主节点和标准槽位集群。一个进程可以运行多个相互隔离的代理监听器;每个 proxies[] 项独立管理连接限制、连接资源、只读策略、指标和运行状态。
Dragonfly HA 最小配置 · 生产协调集群配置 · 部署指南 · 运维与恢复
NARIX 当前提供五种数据面模式:
replication-ha:托管复制模式,Dragonfly HA 是其特色使用场景;按backend_profile加载产品适配器,执行探测、保护、fencing 和协同切换,除 Kvrocks 外还可动态编排持久化责任。standalone:固定单后端透明代理。sentinel:按 Redis Sentinel 客户端协议发现并校验当前主节点,切主后更新本地连接资源。cluster:标准槽位 Cluster 的单入口代理,负责拓扑加载、槽位路由、MOVED/ASK和跨节点聚合。cluster-node-proxy:为标准槽位 Cluster 的每个节点提供一对一代理地址,并改写集群拓扑和重定向地址。
Dragonfly 提供数据存储和主从复制,NARIX 的 replication-ha 控制面负责持续判断“谁可以接流、谁可以接管、谁承担快照、谁有权修改拓扑”。业务客户端保留普通 Redis 连接方式,切换时由 NARIX 收敛路由并关闭旧代连接,客户端重连后进入当前安全主节点。
业务客户端(普通 Redis 客户端,零 SDK 改造)
│ 稳定接入地址
┌────────────▼────────────┐
│ NARIX 数据面 │ 只路由到唯一已验证主节点
│ 保护模式 fail-closed │ 切主后主动关闭旧代长连接
└────────────┬────────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
master ◄─── replica replica
▲ │
└─────────────────────────┘
全部副本直连当前主节点;级联漂移进入受控收敛
NARIX HA 控制面对全部节点持续探测并执行:
候选延迟门禁 · 故障确认后先断路 · fencing/切换 · 副本拓扑收敛
动态持久化编排(单节点由主节点承担快照;多节点责任在副本间交接并验证)
多实例互斥:local-file / Redis 租约 / 内置 2 节点与多数派协调集群
| Dragonfly HA 的运行职责 | NARIX 的处理方式 |
|---|---|
| 主节点故障与恢复 | 连续故障确认后关闭路由;验证候选复制状态、取得动作权威并完成 fencing 后切主,结果确认后开放新路由。 |
| 多个代理实例 | 同机文件租约、独立 Redis 租约或内置协调集群互斥控制动作;多机生产优先使用至少三个协调成员。 |
| 不确定拓扑与多主 | 缺少安全证据时保持保护,管理端给出原因;未确认额外主节点不能因暂时不可达而被忽略。 |
| 快照对业务的影响 | 多节点稳态把快照责任放在副本,合格副本充足时保留无快照热备;交接遵守先启用并验证新 owner、再停用旧 owner 的顺序。 |
| 级联与错误上游 | 在控制权威有效时重新分配副本,使其直连当前主节点;失败退避并保持保护。 |
| 运维变更 | 管理接口与自动切主共用安全门禁;配置先校验和准备,再提交发布,失败候选保留原配置。 |
| 业务可观测性 | 提供主从拓扑、保护原因、持久化责任、配置状态、Prometheus 指标和 Grafana 仪表盘。 |
切代和删除先退休旧控制运行代;产品适配器在外部步骤前后复验退休状态、租约或动作令牌,阻止旧句柄继续发起控制动作。已经发送到后端的命令无法撤回,客户端在断连时仍可能面对结果未知,需按业务幂等语义处理。内置协调集群记录 HA 观察、切换结果与持久化所有权,控制结果先提交,再发布安全路由。详细边界见 运维指南 与 后端控制能力与部署约束。
Dragonfly HA 还要管理快照责任。启用 ha.persistence.enabled: true(Kvrocks 除外)后,NARIX 还会编排"谁来承担持久化":单节点部署由主节点承担快照;多节点稳态把责任交给合格副本,让主节点不被快照 I/O 拖累;无法确认合格责任节点时按 fail_closed 策略保护路由。
推荐生产稳态是 1 主 + 1 热备 + 至少 1 快照节点(至少 3 个健康节点)。业务只发往当前主节点,其余节点都直接跟随主节点:
业务读写
│
▼
┌────────────────────────┐
│ 当前主节点 (master) │ 稳态关闭周期快照,不被快照 I/O 拖累
└────────────┬───────────┘
│ 全部副本直连主节点(级联漂移进入受控收敛)
┌───────────────┼────────────────┐
▼ ▼ ▼
热备 hot-standby 快照节点 1 快照节点 N
关周期快照 执行周期快照 执行周期快照
专职故障接管 承担持久化责任 承担持久化责任
三个角色由运行时根据节点实际主从状态、复制延迟和稳定时间动态选择,nodes 只是候选清单——不能把某个地址永久钉成主节点或热备。运行时按当前健康从节点数量在三种拓扑间自动切换:
| 健康主 | 合格从 | 拓扑(状态接口 topology) |
说明 |
|---|---|---|---|
| 单节点配置:1 | 0 | single-master-snapshot |
只有配置本来就只有一个节点时,主节点承担快照。 |
| 多节点配置:1 | 0 | none / protected |
多节点拓扑失去全部合格副本时不把持久化责任偷渡回主节点;按 fail_closed 保持保护并等待副本恢复。 |
| 1 | 1 | single-replica-snapshot |
自动取消独立热备,唯一从节点既做快照 owner 又是故障切换候选;快照 I/O 与接管职责落在同一节点,属可用性降级。 |
| 1 | ≥2 | hot-standby-replica-snapshots |
选 1 个稳定低延迟从节点做无快照热备(专职接管),其余合格从节点承担快照。这是推荐稳态。 |
节点数建议:3 个是满足"1 主 + 1 热备 + 1 快照"的最低数量;若要求任意 1 个节点故障后仍保留这三个角色,建议至少 4 个节点(1 主 + 1 热备 + 2 快照)。主节点故障后原热备优先晋升;只有 3 个节点时,在故障节点恢复或补充新节点前会暂时退化为"1 主 + 1 快照从节点"。
安全约束:启用严格持久化策略后,启动阶段会保持保护,直到首次 owner 与后端配置完成验证。交接严格按“启用新 owner → 验证 checkpoint → 停用全部旧 owner → 提交协调结果 → 发布本地拓扑”执行,任一步失败都不会把新拓扑标记为已验证;产品适配器内部每条配置写和验证轮询都会复验动作权威,多配置中途失败会在权威仍有效时恢复调用前配置。已发布拓扑也会持续与后端真实配置复核,外部 CONFIG/cron 漂移不会被本地缓存掩盖;proxy-cluster 提交的证据覆盖完整 owner 与复制链路,而不是只记录首个 owner。已知旧 owner 缺席时不能假定其已经停用,持久化无法安全收敛且 fail_closed: true 时进入保护模式而非静默失去持久化。Kvrocks 是例外——每个节点自管 RocksDB/WAL,必须 ha.persistence.enabled: false,NARIX 只收敛主从拓扑、不分配热备或快照角色。
下表给出普通 RESP 接入的最低支持版本,支持该版本及以上具有相同协议与原生能力的版本。版本下限不表示所有新命令、参数、模块、拓扑和持久化能力都存在;命令语义以目标后端为准。read_only 使用 NARIX 的查询白名单,拒绝未知形态和所有修改操作,其范围见 命令矩阵。
| 后端 | backend_profile |
最低 RESP 接入版本 | 模式与原生能力边界 |
|---|---|---|---|
| Redis | redis |
6.0.0 及以上 | Sentinel 与标准 Cluster 可用;较新版本的 Function、模块和管理能力不会补到旧后端。 |
| Valkey | valkey |
7.2.5 及以上 | Sentinel、标准 Cluster;继承的 7.2.4 标签及已撤回的 8.0.8 不在支持范围。 |
| Dragonfly | dragonfly |
1.7.0 及以上 | replication-ha 的复制控制要求至少 1.9.0;不准入标准 Cluster 或 Sentinel。1.7.0 需关闭后端远端版本检查,并使用该版本的 save_schedule 参数。 |
| Apache Kvrocks | kvrocks |
2.10.1 及以上 | 标准 Cluster 和托管复制;各节点自管 RocksDB/WAL,禁止 NARIX 动态持久化编排。 |
| Microsoft Garnet | garnet |
2.1.0 及以上 | 标准 Cluster;不准入托管复制 HA 或 Sentinel。Range/Vector 还依赖后端相应模块及运行依赖,不能仅凭命令名存在认定可用。 |
| KeyDB | keydb |
5.0.0 及以上 | 标准 Cluster 最低为 5.1.0;原生 Cluster TLS 要求至少 6.2.0 且后端构建启用 TLS。托管复制只允许单主拓扑,禁止 active-replica/multi-master。 |
| Redict | redict |
7.3.0 及以上 | Sentinel、标准 Cluster;托管复制与动态持久化仍须具备下述控制能力。 |
| Pika | pika |
4.0.4 及以上 | standalone 透明接入;Pika/Codis 槽协议不等于标准 Redis Cluster;使用 RESP2。 |
| Tendis | tendis |
2.0.6 及以上 | 标准 Cluster 与节点代理;使用 RESP2,不准入 Sentinel 或托管复制 HA。RocksDB 构建变体须与后端数据目录格式相容。 |
托管复制与动态持久化采用独立下限:
| 后端 | 托管复制 HA 最低版本 | 动态持久化最低版本 |
|---|---|---|
| Redis | 6.2.0 及以上 | 7.0.0 及以上 |
| Valkey | 7.2.5 及以上 | 7.2.5 及以上 |
| Dragonfly | 1.9.0 及以上 | 1.15.0 及以上,须满足下述 ACK 周期条件 |
| Redict | 7.3.0 及以上 | 7.3.0 及以上 |
| KeyDB | 6.2.0 及以上,单主复制 | 6.2.0 及以上 |
| Kvrocks | 2.16.0 及以上 | 不提供,节点自管 RocksDB/WAL |
Dragonfly 的副本延迟门禁使用 master_last_io_seconds_ago 的秒级 I/O 年龄,并扣除一秒采样粒度;它不等同于字节 offset 差。Dragonfly 1.15.0 使用严格 ha.persistence.require_zero_lag: true 时,后端启动须显式设置 --replication_acks_interval=1000。该版本默认 3000ms ACK 周期可能让健康空闲链路的年龄达到 2,导致持久化候选被拒绝、路由保持保护;NARIX 不会为取得 Ready 自动放宽此门禁。断链、全量同步、未知复制状态仍不可作为安全候选。
HA 和动态持久化有独立的原生能力要求:Redis-family 的计划切换需要 FAILOVER TO,副本分配需要动态复制凭据及 REPLICAOF;Redis、Valkey、Redict 的 checkpoint 需要 INFO persistence 中的 rdb_saves,KeyDB 使用严格推进的 LASTSAVE。Dragonfly 动态持久化需要可读写的 snapshot_cron、dbfilename 以及可验证的 LASTSAVE。普通 RESP 版本下限不替代这些要求;能力缺失、权限不足或结果无法确认时,相应动作失败并保留保护。完整合同见 后端控制能力与部署约束。
原生缺席、占位或错误语义不会由透明代理变成完整功能。例如 Dragonfly 的 LATENCY 固定空返回不表示具有延迟诊断;旧 Tendis 的部分管理入口只有占位或无法调用;Garnet 2.1.0 至 2.2.4 的原生 FAILOVER 存在双端变为副本的边界,该路径不属于可用切换合同。Garnet 的向量计数与删除后状态也受后端版本限制。具体命令路由和兼容转换见 命令矩阵。
配置层的模式准入如下:
| 模式 | 可用 backend_profile |
|---|---|
standalone |
redis、valkey、dragonfly、kvrocks、garnet、keydb、redict、pika、tendis |
sentinel |
redis、valkey、redict |
cluster |
redis、valkey、kvrocks、garnet、keydb、redict、tendis |
cluster-node-proxy |
redis、valkey、kvrocks、garnet、keydb、redict、tendis |
replication-ha |
redis、valkey、dragonfly、redict、kvrocks、keydb |
注意:
- Pika/Codis 槽接口不是标准 Redis Cluster 协议,因此 Pika 使用
standalone透明接入,不能配置为cluster或cluster-node-proxy。 sentinel只消费 Sentinel 已提交的主节点拓扑,不发起选主、REPLICAOF、fencing 或 Sentinel 配置修改。- 六个托管复制产品统一使用
mode: replication-ha,由backend_profile选择适配器,不存在产品专属模式入口。 - Kvrocks 的 replication-ha 只管理主从拓扑,必须设置
ha.persistence.enabled: false;Redis、Valkey、Redict、KeyDB 和 Dragonfly 可使用产品原生动态持久化。 - 云托管 RESP 服务的 TLS、ACL、网络和故障转移须满足服务商接口及部署约束,不能仅凭 RESP 接入兼容推定可用。
- 命令分类、路由策略和模式限制见
command-matrix.md;版本下限、模式准入和原生能力约束以本节及控制能力合同为准。
以下是指定负载下的最佳实测,不是典型值或容量保证。吞吐取完整配对中 NARIX 的最高 QPS;延迟取 NARIX p99 最低的完整配对,同一行的各个分位都来自同一次配对。每种负载至少包含三次有效重复,异常样本按直连、代理和参考路径整组排除。
环境为 Apple M1 Pro(10 核、16 GiB),Docker Linux arm64 虚拟机配置 10 vCPU、约 7.75 GiB 内存。后端、代理、客户端分别固定到互不重叠的两颗 vCPU;后端内存上限 768 MiB,代理和客户端各 512 MiB,NARIX 使用两个 Tokio worker。程序使用 Rust 1.95 的 release 构建,lto=thin、codegen-units=1。采用同一 Docker 网络内的 TCP、RESP2、持久连接,无 TLS;每次预热 15 秒、测量 60 秒。HA 为一主一从的稳态路由,探测周期 2 秒,自动切换和持久化编排关闭;Dragonfly 后端也关闭快照。
构建列是构建源快照 SHA-256 的前 12 位。当前业务实现的测量构建为 f13cdca88499;其他行仅描述各自标注的构建,数据不跨构建合并。吞吐表均为热点 GET、64 字节值,直连列与 NARIX 列来自同一次配对。
| 后端 | 模式 | 连接数 / pipeline | NARIX QPS | 直连 QPS | 构建 |
|---|---|---|---|---|---|
| Redis 6.0.0 | standalone |
32 / 16 | 1,425,690 | 1,485,763 | f13cdca88499 |
| Redis 6.2.0 | replication-ha |
32 / 16 | 1,576,003 | 1,513,763 | b869f93c7fd7 |
| Redis 8.10.3 | replication-ha |
32 / 16 | 1,565,762 | 1,516,921 | b869f93c7fd7 |
| Dragonfly 2.0.2 | standalone |
32 / 16 | 1,236,086 | 1,449,221 | 83135bd29311 |
| Dragonfly 2.0.2 | replication-ha |
32 / 16 | 1,418,180 | 1,532,165 | b68c94ee83d3 |
| Dragonfly 2.0.2 | replication-ha |
128 / 64 | 1,960,180 | 1,938,193 | 23223f27435c |
容量负载下各路径达到的速率不同;批量处理与调度也可能使代理路径的容量实测高于直连。高吞吐不代表低尾延迟:上表 128 连接、pipeline 64 的 Dragonfly HA 配对中,NARIX 的绝对 p99 约为 20.19 ms。因此额外延迟使用下面的固定请求速率配对单独描述。
额外延迟 = 经 NARIX 的命令完成延迟分位数 − 直连的同一分位数,单位为 µs。例如直连 150µs、经代理 160µs,差值就是 10µs。下表均为 Dragonfly 2.0.2、32 连接、pipeline 16、64 字节热点 GET,设定速率为每秒 1,000,000 条命令。
| 模式 | 构建 | p50 差值 | p95 差值 | p99 差值 | p99.5 差值 | p99.9 差值 |
|---|---|---|---|---|---|---|
replication-ha |
23223f27435c |
+35.840 | −2.048 | −20.480 | −32.768 | −126.976 |
standalone |
83135bd29311 |
+79.872 | +100.352 | +139.264 | +151.552 | +200.704 |
standalone |
f13cdca88499 |
+82.944 | +145.408 | +180.224 | +188.416 | +294.912 |
延迟从客户端发出该命令时计到收到对应完整响应,包含网络、后端执行和排队。它不含客户端尚未发出命令时的等待;若从计划发送时刻计时,上述三行 NARIX 的 p99 分别约为 1.71 ms、39.32 ms、28.18 ms。60 秒窗口内,NARIX 分别完成 59,999,568、59,999,472、59,999,440 条命令,仍有 432、528、560 条计划命令未发出,不能称为全部计划需求均已完成。
这些分位差不是逐命令代理内部耗时的分布,负差值也不表示负的内部耗时。直方图桶相对宽度不超过 0.78125%,表中采用桶上界计算差值;pipeline 不用于除算单命令延迟。实际开销随模式、连接数、值大小、负载率和宿主调度变化,不能从最佳 GET 数据推定混合读写、切换期间或所有尾部分位的性能。
使用独立的代理项并设置 read_only: true,可为开发排查和运维查询提供受限入口。允许的读命令按后端及参数形态分类;写命令、脚本执行、管理修改、复制控制和未知子命令在发往后端前拒绝。同一解析批次只要包含一条不允许的命令,整批返回 READONLY,不会先执行其中的读命令;跨批次不提供事务回滚。
readonly 不会授予额外后端权限,也不隐藏查询可见的敏感数据;仍应配置前端认证、后端最小权限和网络隔离。需要旁路跟随现有 HA 控制面时,可同时使用 ha.observer: true:observer 不执行后端控制写,业务命令是否只读仍由 read_only 决定。
需要 Rust 1.94 或更高版本。全部第三方依赖来自 crates.io,使用仓库中的 Cargo.lock 固定版本与校验和,不需要本地框架源码。NARIX 以二进制、源码或容器分发,保留 publish = false:
cargo build --release --locked使用外部配置启动:
target/release/narix --config=/etc/narix/narix.yml也可以通过环境变量指定:
APP_CONFIG_FILE=/etc/narix/narix.yml target/release/narix外部文件选择优先级为 --config → APP_CONFIG_FILE → 兼容变量 NARIX_CONFIG,未设置或空值继续选择下一项。指定文件不可读或校验失败时拒绝加载,不回退到低优先级文件。进程会在打开业务监听前完成配置解析、强类型校验、代理名称去重和监听地址冲突检查;失败时直接退出。
准备 deploy/narix/config/narix.yml,将业务监听设为 0.0.0.0:6379、管理监听设为 0.0.0.0:18080,并填写真实后端地址和凭据。创建 deploy/narix/data、deploy/narix/logs,确保镜像用户 10001:10001 可读配置、可写数据和日志目录。
docker build -f docker/Dockerfile -t narix:1.0.0 .
docker run -d --name narix \
--restart unless-stopped --stop-timeout 70 \
-p 6379:6379 -p 127.0.0.1:18080:18080 \
-v "$PWD/deploy/narix/config:/etc/narix:ro" \
-v "$PWD/deploy/narix/data:/var/lib/narix" \
-v "$PWD/deploy/narix/logs:/usr/local/logs/narix" \
-v /etc/localtime:/etc/localtime:ro \
narix:1.0.0镜像默认 APP_CONFIG_FILE=/etc/narix/narix.yml。配置目录只读,数据与日志保留在宿主机,/etc/localtime 只读挂载使容器使用宿主时区;该文件须在 Docker 宿主上存在且可挂载。协调数据路径放在 /var/lib/narix 下;每个协调成员使用独立目录。示例发布业务端口,管理端口仅限宿主回环访问。后端在另一个容器时加入双方共用的 Docker 网络。
各代理模式、HA 协调、只读入口和多监听器的完整 docker run 示例见 Docker Hub README;挂载、热更和镜像分发说明见容器部署。
以下配置只保留启动和基本运维所需字段。示例密码和 token 必须在部署前替换;后端需要 ACL 或密码时再增加 username、password。
托管复制 HA 的唯一模式入口,架构与对比见上文Dragonfly HA 架构。配置层面的要点:
backend_profile选择产品适配器,当前放行六个后端产品;产品切换语义差异(Redis 系FAILOVER TO、Dragonfly 先升后降、KvrocksCLIENT PAUSE+SLAVEOF)由适配器吸收,管理接口统一为/ha/*。ha块是后端无关的控制面配置:探测周期与独立探测超时、故障判定阈值、复制延迟门禁、auto_failover开关、fencing 模式、协调器(none/local-file/redis/proxy-cluster)。coordinator.mode省略时自动解析:组了内置协调集群(coordination.enabled=true)自动为proxy-cluster(集群里只有 leader 切主,其余节点只观察);单实例自动为none(进程内串行)。组集群时显式配非proxy-cluster会被启动校验拒绝,从源头堵死多实例各自切主的双主风险。- 产品持久化参数放在
ha.persistence.<product>子块;Kvrocks 必须ha.persistence.enabled: false。 - 自动故障转移默认开启(
ha.auto_failover: true):主节点达到连续失败阈值后先关闭路由,再经过协调、fencing 和候选门禁恢复服务。默认fencing.mode: manual是无需脚本的软隔离,允许旧主恢复到被降级之间存在短暂双写风险;生产零脑裂目标必须使用经真实基础设施演练的external-command。 - 人工拓扑动作不是绕过安全门禁的后门:
failover/switchover/promote/replicaof/fence与自动切主使用同一协调权威;人工promote也必须先 fencing 旧主。产品适配器在每条角色/复制写命令及等待确认期间持续复验租约或动作令牌,切主结果成功提交后才发布本地新主路由。 - 观察者模式(
ha.observer: true):控制面只探测和跟随,绝不发送后端控制命令,手动拓扑接口一并拒绝;切路由需要证据:旧主降级证词立即跟随,旧主永久死亡时按“确认宕机 + 接管者连续稳定”的受限通道自动恢复;证据不足与双主期间进入保护。observer不限制业务命令,旁路只读端点必须同时配置read_only: true。 - 运维全套接口:
GET /ha/topology|master|replicas,POST /ha/failover|switchover,POST /ha/node/{node}/promote|replicaof/{master}|fence。
这是以 Dragonfly 为例的单实例自动切换最小配置,适合本地验证或能接受软隔离风险的单控制面部署。nodes 中每项格式为 客户端地址@复制地址;接入其他支持的产品时替换 backend_profile 和节点地址,并使用下方对应全量 YAML 的产品持久化块:
admin: # 管理端 HTTP 服务配置。
enabled: true # 启用健康、HA 状态和指标接口。
listen: 127.0.0.1:18080 # 管理端监听地址。
token: "replace-with-a-long-random-admin-token" # 管理 API 令牌,部署前必须替换。
proxies: # 托管复制 HA 业务代理项列表。
- name: replication-ha-dragonfly # 代理项唯一名称。
backend_profile: dragonfly # 选择 Dragonfly 的 replication-ha 适配器。
mode: replication-ha # 托管复制 HA 的唯一模式入口。
listen_host: 0.0.0.0 # 业务 listener 绑定地址。
listen: 7001 # 客户端连接该托管复制代理的端口。
nodes: 198.51.100.11:6379@198.51.100.11:6379,198.51.100.12:6379@198.51.100.12:6379 # 节点清单,每项为客户端地址@复制地址,使用文档专用地址。
frontend_password: "replace-with-a-long-random-client-password" # 客户端连接 NARIX 使用的密码。
auth_mode: terminate # NARIX 终止前端认证并独立认证后端。
ha: # 后端无关的 HA 控制面配置。
auto_failover: true # 默认即 true:确认主故障后先保护路由,再自动选择并提升候选。
fencing: # 旧主隔离策略。
mode: manual # 默认软隔离:切主后靠 REPLICAOF 把旧主降级为副本;零脚本,但存在短暂双写风险。
coordinator: # 单实例用默认 none(进程内串行化);多实例部署必须改 proxy-cluster/redis 防双主。
mode: none上面几乎全是默认值——
auto_failover、fencing.mode、coordinator.mode都可省略。默认值解决的是单进程动作串行和自动恢复,不承诺零脑裂。生产强隔离把fencing.mode改为external-command并配置隔离程序;跨机器多实例改用proxy-cluster或独立 Redis 协调器,完整模板见下方。
完整单 NARIX 实例配置:docs/configuration/replication-ha-dragonfly.yml
内置协调集群生产模板:docs/configuration/replication-ha-dragonfly-proxy-cluster.yml
其他产品完整配置:
生产自动切换必须同时配置可靠的 external-command fencing 和与部署范围匹配的互斥机制:单实例可使用进程内锁,但必须保证没有进程重叠;跨进程/跨机器部署使用 proxy-cluster 或独立 Redis。跨机器新部署优先使用至少三个成员的内置多数派协调;local-file 只协调同机进程。
固定单后端的透明代理。业务侧看到的仍是一个普通 RESP 端点,NARIX 在中间补齐直连拿不到的治理能力:
- 全命令类别透明透传,前端 pipeline 严格保序;前端是 pipeline 时到后端同样保持 pipeline。
- Pub/Sub、阻塞命令、事务和连接绑定命令自动进入 DedicatedTunnel,独享连接并受活跃上限、排队容量与获取超时约束,慢消费者不会拖垮普通请求的连接池。
auth_mode: terminate前端认证由 NARIX 终止、后端独立认证,业务侧不再持有后端密码;backend-inject兼容旧内网免认证接入。read_only: true时写命令与全部脚本执行入口按失败关闭原则拒绝,只读查询保持可用。- 每个代理项独立的连接上限、队列、帧/批大小与超时预算,以及独立指标;NARIX 到后端支持受 CA/SNI 校验的 RESP TLS 与可选 mTLS。
- 九个后端产品全部准入(见上方模式准入表);Pika/Codis 等非标准槽位产品也经由该模式透明接入。
下面以 Redis 为例。接入其他支持的 KV 时,替换 backend_profile、host 和 port:
admin: # 管理端 HTTP 服务配置。
enabled: true # 启用健康、状态和指标接口。
listen: 127.0.0.1:18080 # 管理端监听地址。
token: "replace-with-a-long-random-admin-token" # 管理 API 令牌,部署前必须替换。
proxies: # 业务代理项列表。
- name: redis-primary # 代理项唯一名称。
backend_profile: redis # 后端产品能力档案。
mode: standalone # 固定单后端模式。
listen_host: 0.0.0.0 # 业务 listener 绑定地址。
listen: 7001 # 客户端连接 NARIX 的端口。
host: 127.0.0.1 # 固定后端主机。
port: 6379 # 固定后端端口。
frontend_password: "replace-with-a-long-random-client-password" # 客户端连接 NARIX 使用的密码。
auth_mode: terminate # NARIX 终止前端认证并独立认证后端。完整配置:docs/configuration/standalone.yml
面向已有 Redis Sentinel 体系的动态单主代理。业务客户端不需要实现 Sentinel 协议,只连 NARIX 一个稳定地址:
- 按 Sentinel 客户端协议查询已提交的当前主节点,并校验候选节点角色确实为 master 后才路由,不盲信 Sentinel 应答。
- 订阅
+switch-master事件即时感知切主,另有周期刷新兜底;切主后更新本地连接资源并执行安全路由,无法确认安全主节点时拒绝新连接而不是乱路由。 - 定位是 Sentinel 拓扑的消费者:不发起选主、不执行
REPLICAOF、不做 fencing、不修改 Sentinel 配置——需要 NARIX 亲自管理主从时应使用replication-ha。 - Sentinel 控制连接与业务数据连接的认证、TLS 完全独立配置,互不复用。
- 当前准入
redis、valkey、redict。
业务客户端只连接 NARIX;NARIX 查询 Sentinel、校验候选节点为 master,再把业务请求发送到当前主节点:
admin: # 管理端 HTTP 服务配置。
enabled: true # 启用健康、状态和指标接口。
listen: 127.0.0.1:18080 # 管理端监听地址。
token: "replace-with-a-long-random-admin-token" # 管理 API 令牌,部署前必须替换。
proxies: # 业务代理项列表。
- name: redis-sentinel # 代理项唯一名称。
backend_profile: redis # Sentinel 模式当前准入 redis、valkey、redict。
mode: sentinel # Sentinel 动态单主模式。
listen_host: 0.0.0.0 # 业务 listener 绑定地址。
listen: 7001 # 客户端连接 NARIX 的端口。
sentinel_master_name: mymaster # Sentinel 监控的服务名称。
sentinel_nodes: 192.0.2.11:26379,192.0.2.12:26379,192.0.2.13:26379 # Sentinel 控制节点。
frontend_password: "replace-with-a-long-random-client-password" # 客户端连接 NARIX 使用的密码。
auth_mode: terminate # NARIX 分别处理前端、Sentinel 和数据节点认证。完整配置:docs/configuration/sentinel.yml
标准槽位 Cluster 的单入口代理:业务客户端把 NARIX 当普通单机 Redis 使用,不需要 Cluster 客户端能力。
- NARIX 负责拓扑加载与周期刷新、按 key 槽位路由、吸收
MOVED/ASK重定向;已登记的跨槽聚合命令按槽拆分、并发执行并聚合结果;MSET、脚本等要求同槽的命令仍拒绝跨槽请求,pipeline 响应严格保序。 - 适合让不支持 Cluster 协议的旧客户端、框架或语言栈接入集群,由代理处理槽位路由与重定向;故障、超时和不可执行的命令仍会返回给客户端。
- 共享后端通道固定使用 RESP2;
HELLO 3明确返回NOPROTO,不虚假宣称 RESP3。会话状态类命令(如RESET)在单入口语义下无法安全映射到具体节点时明确拒绝。 - 配置热更新预检会刷新拓扑并校验 16384 个槽位完整且无冲突后才发布。
- 当前准入
redis、valkey、kvrocks、garnet、keydb、redict、tendis。
nodes 是标准槽位 Cluster 的 seed 列表:
admin: # 管理端 HTTP 服务配置。
enabled: true # 启用健康、状态和指标接口。
listen: 127.0.0.1:18080 # 管理端监听地址。
token: "replace-with-a-long-random-admin-token" # 管理 API 令牌,部署前必须替换。
proxies: # 业务代理项列表。
- name: redis-cluster # 代理项唯一名称。
backend_profile: redis # 标准槽位后端能力档案。
mode: cluster # Cluster 单入口模式。
listen_host: 0.0.0.0 # 业务 listener 绑定地址。
listen: 7001 # Cluster Client 连接 NARIX 的端口。
nodes: 192.0.2.11:6379,192.0.2.12:6379,192.0.2.13:6379 # 逗号分隔的 Cluster seed,使用文档专用地址。
frontend_password: "replace-with-a-long-random-client-password" # 客户端连接 NARIX 使用的密码。
auth_mode: terminate # NARIX 终止前端认证并独立认证后端。完整配置:docs/configuration/cluster.yml
保留 Cluster Client 语义的节点级代理:业务继续使用标准 Cluster 客户端,但每个真实节点都经由一个 NARIX listener 暴露。
- 改写
CLUSTER SLOTS、CLUSTER NODES、MOVED和ASK中的节点地址为公布地址,部署侧须确保这些公布地址从客户端网络可达。 aliases用于归一化后端可能返回的主机名、容器名或内网地址,防止重定向泄漏业务不可达的原始地址。- 适合客户端位于 NAT/防火墙之外、或需要为每个集群节点独立做连接治理与指标的场景;terminate 模式下同样由 NARIX 终止前端认证。
- 槽位迁移、
MOVED/ASK与节点故障语义与直连集群一致,由客户端按 Cluster 协议处理。 - 当前准入
redis、valkey、kvrocks、garnet、keydb、redict、tendis。
每个真实 Cluster 节点必须有唯一的代理监听端口;advertise_host/advertise_port 是返回给 Cluster Client 的可达地址:
admin: # 管理端 HTTP 服务配置。
enabled: true # 启用健康、状态和指标接口。
listen: 127.0.0.1:18080 # 管理端监听地址。
token: "replace-with-a-long-random-admin-token" # 管理 API 令牌,部署前必须替换。
proxies: # 业务代理项列表。
- name: redis-cluster-nodes # 代理项唯一名称。
backend_profile: redis # 标准槽位后端能力档案。
mode: cluster-node-proxy # Cluster 节点一对一代理模式。
listen_host: 0.0.0.0 # 子 listener 默认绑定地址。
cluster_node_advertise_host: narix.example.internal # 返回给 Cluster Client 的统一可达主机。
frontend_password: "replace-with-a-long-random-client-password" # 客户端连接节点代理使用的密码。
auth_mode: terminate # NARIX 终止前端认证并独立认证后端。
node_proxies: # 真实节点与代理 listener 的映射表。
- backend: 192.0.2.11:6379 # 第一个真实 Cluster 节点,示例使用文档专用地址。
listen: 17001 # 第一个节点代理监听端口。
advertise_port: 17001 # 返回给 Cluster Client 的第一个代理端口。
- backend: 192.0.2.12:6379 # 第二个真实 Cluster 节点。
listen: 17002 # 第二个节点代理监听端口。
advertise_port: 17002 # 返回给 Cluster Client 的第二个代理端口。
- backend: 192.0.2.13:6379 # 第三个真实 Cluster 节点。
listen: 17003 # 第三个节点代理监听端口。
advertise_port: 17003 # 返回给 Cluster Client 的第三个代理端口。完整配置:docs/configuration/cluster-node-proxy.yml
健康和就绪端点不要求 token:
curl -fsS http://127.0.0.1:18080/health
curl -fsS http://127.0.0.1:18080/ready状态与指标接口需要管理 token:
curl -fsS \
-H 'Authorization: Bearer replace-with-a-long-random-admin-token' \
http://127.0.0.1:18080/status
curl -fsS \
-H 'Authorization: Bearer replace-with-a-long-random-admin-token' \
http://127.0.0.1:18080/metrics负载均衡健康检查应使用 /ready,不要使用只表示进程存活的 /health。管理端还接受 X-Admin-Token: <token>。
业务连接检查:
redis-cli -h 127.0.0.1 -p 7001 \
-a replace-with-a-long-random-client-password PING配置加载优先级从低到高:
zcf/application.yml
同目录 application-${NARIX_PROFILE}.yml
--config、APP_CONFIG_FILE 或 NARIX_CONFIG 选定的外部文件
外部文件同目录的 ${name}-${NARIX_PROFILE}.yml
NARIX_ 字段环境变量
${...} 配置占位符解析
支持 YAML、JSON 和 TOML。文件显式写出 proxies[] 或 node_proxies[] 时,该数组表示完整期望集合:同 name 或 backend 的条目继承低优先级文件中未覆盖的字段,未出现在高优先级数组中的条目会被删除;省略整个数组才表示全部继承。环境变量仍按身份或下标定向覆盖,不删除其他数组项。
默认开启配置热更新,reload.poll_interval_ms 默认 1000(1 秒),设置 10000 即 10 秒。修改外部配置后,NARIX 会在连续两次读取到相同有效摘要时尝试发布;也可以显式校验或发布。涉及 HA 拓扑、持久化责任或未确认多主证据时,发布仍须通过旧运行代的安全预提交,失败会保留原配置和原运行代:
curl -fsS \
-H 'Authorization: Bearer replace-with-a-long-random-admin-token' \
-X POST http://127.0.0.1:18080/config/validate
curl -fsS \
-H 'Authorization: Bearer replace-with-a-long-random-admin-token' \
-X POST http://127.0.0.1:18080/config/reload单节点部署直接切换代理运行代。启用进程级协调集群后,只需在任意一个 NARIX 成员修改并提交一次;请求会转交领导节点,以多数派预检和共识提交同步到其他成员。落后成员在追平已提交 revision 前不开放数据面,本地旧文件不能覆盖集群新版本。
更多配置:
- 完整配置说明、认证、覆盖规则与环境变量
- standalone 全量 YAML
- sentinel 全量 YAML
- cluster 全量 YAML
- cluster-node-proxy 全量 YAML
- replication-ha + Redis 全量 YAML
- replication-ha + Valkey 全量 YAML
- replication-ha + Redict 全量 YAML
- replication-ha + KeyDB 全量 YAML
- replication-ha + Kvrocks 全量 YAML
- replication-ha + Dragonfly 全量 YAML
- replication-ha + Dragonfly 内置协调集群 YAML
- 内置最小安全配置
- 配置热更新、集群一致性与故障恢复
默认输出全部 WARN、异常 ERROR 以及 NARIX 启停、配置生效、控制权、角色与保护态变化等关键 INFO。正常请求和成功的周期探测不逐条记录。
application:
name: narix
log:
level: ${NARIX_LOG_LEVEL:warn,narix=info}
path: ${NARIX_LOG_PATH:/usr/local/logs/${application.name}}
max_file_size: 100MB
total_size_cap: 1GB
max_history_days: 7
split_error_file: true
reload:
enabled: true
poll_interval_ms: 1000日志目录通过环境变量覆盖,例如 NARIX_LOG_PATH='/var/log/${application.name}';占位符由配置加载器解析为应用名。单文件上限为 100 MB,归档总量上限为 1 GB,保留 7 天。RUST_LOG 优先于 NARIX_LOG_LEVEL,环境覆盖存在时修改同名 YAML 字段不会改变有效值。
日志级别、目录、格式与轮转策略支持事务热更新。整份候选先解析、校验和准备,任何一步失败都不替换已生效配置;运行代安装失败按事务回滚,回滚不完整时保持业务门禁关闭。成功提交后才采用新的轮询周期。配置来源、节点本地字段及不可热更字段见配置参考,日志关闭与丢弃边界见日志说明。
GET /metrics 暴露进程 CPU、RSS、线程、文件描述符、前后端连接、命令、pipeline、DedicatedTunnel、Cluster、Sentinel 和托管复制 HA 指标。仓库内置的监控文件:
| 文件 | 用途 |
|---|---|
dashboards/prometheus.yml |
单个 NARIX 进程抓取模板 |
dashboards/prometheus-cluster.yml |
多个 NARIX 节点逐节点抓取模板 |
dashboards/grafana-datasource.yml |
Grafana Prometheus 数据源 |
dashboards/grafana-dashboard-provider.yml |
Grafana dashboard provider |
dashboards/narix-overview.json |
支持集群、节点和代理筛选的 NARIX 仪表盘 |
NARIX 集群中每个进程都独立暴露管理端,Prometheus 必须逐节点抓取,不能只抓负载均衡地址。集群内各任务的 environment 和 narix_cluster 标签保持一致,narix_node 必须唯一。详细部署与告警处理见 运维指南。
- 生产业务入口建议使用
auth_mode: terminate,不要无认证暴露代理端口。 - 管理端默认要求 token;
allow_unauthenticated: true仅适用于可信隔离网络。 - 业务 RESP 入口不原生终止 TLS;跨不可信网络时应由受信四层入口、隧道或服务网格终止 TLS。
- NARIX 到业务数据节点支持受 CA/SNI 校验的 RESP TLS;Sentinel 控制连接可独立启用 TLS,两套证书和 ACL 互不复用。
coordination.tls只保护 NARIX 成员间的 gRPC 控制端口,不能替代业务入口加密。- replication-ha 达到主故障阈值、观察到未确认新主或双主时会关闭路由;负载均衡必须按
/ready摘挂。 - 生产自动故障转移必须具备可靠 fencing 和与部署范围匹配的协调门禁;不能把不可确认的旧主直接视为已隔离。
ha.persistence.enabled: true是持久化责任编排,不是零数据丢失 WAL;异步复制仍有 RPO 窗口。- Kvrocks 必须保持
ha.persistence.enabled: false,各节点自己的 RocksDB/WAL、备份和磁盘可靠性由部署侧负责。 - 按文件描述符、后端
maxclients、业务 pipeline 和内存预算设置连接、队列与帧上限。 - cluster-node-proxy 的别名应覆盖可能出现在
CLUSTER SLOTS、CLUSTER NODES、MOVED和ASK中的后端地址。
日志由单一管理器控制过滤、文件输出和轮转;配置解析、指标编码、gRPC 传输、凭据材料和时间换算使用 NASA 设施。NARIX 的配置事务负责候选准备、提交和同代激活,Application 负责进程信号、关键任务监督及资源关闭。RESP 稳态转发直接使用当前运行代持有的句柄,不逐命令加载配置或读取证书。
运行期配置补读与候选文件读取由 NASA Application 共用组件承接,阻塞文件 I/O 在线程池执行,异步调用方通过 .await 让出执行线程。NARIX 保留路由、HA 权威和跨节点配置提交的领域事务。
同步配置和凭据预检完成后,日志文件准备与业务装配共享启动预算。停止时先撤销业务准入,再停止控制任务和排空连接,最后关闭日志。SIGTERM 与 reload 竞争时不得重新开放已停止的业务门禁;资源排空超时按非零退出,运行时不会在应用关闭预算之外再次无限等待阻塞文件 I/O。详细预算见 配置参考。
本项目采用 Apache License 2.0,详见 LICENSE。