Skip to content

多模冗余(XMR)

可用性:两个变体(Full / Tiny)均支持。头文件 onepath_xmr.h

XMR(X-Modular Redundancy,多模冗余)把「N 份冗余 + 投票选举」收敛为按组名 join 的 位置透明角色:一个任务在主机 A 提交,一群 worker(可在任意机器)冗余计算,投票消费端 (可在主机 C)本地投票选出可靠结果。N 任意:1=无冗余、2=DMR(检错)、3=TMR(纠 1 错)、 N=NMR(纠 ⌊(N−1)/2⌋ 错)。

与「三模便捷封装」的区别

三模存储 / 三模计算单节点三通路便捷封装; XMR 是多副本投票的冗余容错层。两者正交、可叠加。

一、设计要点

  • 位置透明的组:一个组 = 一个名字。各角色按组名 join,不假设同机;跨节点天然可用。
  • 每角色一行submit / compute(worker)/ consume(投票消费端)/ store(副本)/ put / getopts=NULL 即全默认。
  • auto-N(存活感知自动计数):worker 上线即被消费端自动计入 N,spawn 几个就是几模 冗余,worker 增减自适应;opts.expected 可钉死。
  • 边缘投票(无单点):投票在消费端本地完成。投票器本身是单点(SPOF)——标准解 是让每个消费端各自投票(等价 triplicated voters),XMR 默认即如此。
  • 端到端完整性:每份结果默认带 CRC32;被翻转的结果在投票前剔除 (opts.integrity = ONEPATH_XMR_NONE 可关)。
  • 可插投票:默认精确多数;opts.vote_fn 可换 median / 阈值 / 取最值等策略。

二、快速开始(跨节点,每角色一行)

c
#include <onepath.h>
#include <onepath_xmr.h>

/* 主机 A — 生产者 */
onepath_xmr_submit(s, "img-infer", data, len);

/* 任意机器 — 每个 worker 一行, spawn N 个 */
static void infer(void *ud, const void *in, size_t n, onepath_xmr_sink_t *sink) {
    /* ... 计算 ... */ onepath_xmr_emit(sink, out, out_len);
}
onepath_xmr_t w; onepath_xmr_compute(s, &w, "img-infer", infer, NULL, NULL);

/* 主机 C — 投票消费端 (= voter + consumer 合并, 边缘投票) */
static void on_result(void *ud, const onepath_xmr_result_t *r) {
    if (r->agreed) use(r->data, r->data_len);   /* 可靠结果 */
    else           handle_no_consensus();        /* DMR 检出分歧 */
}
onepath_xmr_t c; onepath_xmr_consume(s, &c, "img-infer", on_result, NULL, NULL);

存储同理:onepath_xmr_store(副本,spawn N)/ onepath_xmr_put(写)/ onepath_xmr_get (读端按 sign 投票选举)。配套示例程序 onepath_xmr_compute_demoonepath_xmr_store_demo 给出完整可运行版本。

各入口的完整签名、onepath_xmr_opts_t 选项字段、onepath_xmr_result_t 结构与 ONEPATH_XMR_* 常量,见 API 参考 段的链接。

三、N、quorum 与投票

  • N 的来源:默认由存活感知自动计数在线 worker / 副本数;opts.expected 可钉死 (适合 N 固定的场景)。
  • 多数与容错:精确多数需 ⌊N/2⌋+1 票一致,可容忍 ⌊(N−1)/2⌋ 个故障。
    • N=1:无冗余;N=2(DMR):能检错不能纠错(两份分歧 → agreed=0); N=3(TMR):纠 1 错;N=5:纠 2 错。
  • 低延迟快路径:一旦达到多数即选举,不必等齐全部 worker(落后者不阻塞结果)。
  • 自定义投票vote_fn 接收候选数组,返回胜者索引——可实现 median(数值)、阈值 (近似一致)、取最值、加权等策略。

四、可靠性模型与限制(务必阅读)

XMR 用软件冗余屏蔽独立瞬态故障(如不同 worker 各自被偶发错误命中)。它的能力边界 如下。

投票器是单点;用边缘投票化解

多数投票器本身若出错则结果出错。消除单点的标准做法是让每个消费端各自投票(不是共用 一个投票节点)。XMR 默认即「投票消费端」合一:消费端订阅 N 份原始结果并本地投票, 因此:

  • 没有独立「已选举结果」的额外传输跳;
  • 没有单一投票节点单点(每个消费端等价一个独立投票器)。

Case 1:节点有物理加固 / EDAC(纠错存储)

投票消费端在加固节点上投票,结果在该节点可靠。但若把选举结果再传给另一台未加固节点 的消费者,这一跳与远端内存又脱离 XMR 保护、可能再次出错。

建议:要么就地消费(voter+consumer 合一于加固节点),要么远端消费者不要信任转发来 的结果,而是自己也订阅 N 份原始结果本地再投一次(边缘投票)。opts.republish_sign 的 转发仅用于带宽 / 扇出,不应作为跨未加固跳的「可信」结果。

Case 2:无加固 / 无 EDAC

XMR 能赋能到:

  • 屏蔽 worker 阶段的独立瞬态故障(N=3 容 1、N=5 容 2…);
  • 端到端 CRC 把传输中被翻转的结果在投票前剔除,把可靠边界推到消费节点。

但 XMR 不能根除以下风险

  1. 最终合并那一刻:投票消费端自身那一次比较 / 内存若出错,结果仍可能错。软件只能用 边缘投票把它从「单点」降为「多点」,但每个消费节点那一刻的内存仍需该节点有 EDAC 才 彻底可靠。
  2. 共模 / 相关故障:所有 worker 跑相同代码 / 相同硬件时,确定性缺陷、或同一窗口多个 worker 同时被命中,会让多数一致地错,投票失效。抗共模需实现多样性(不同算法 / 不同硬件,即 N-version)。XMR over 同构 worker 只屏蔽独立瞬态故障。
  3. 共享资源:共用电源 / 时钟 / 链路、或同机多 worker 同时失效 → 无保护。

一句话:XMR 提供「可调 N 的独立瞬态故障屏蔽 + 端到端校验 + 无单点的边缘投票」;残留风险 是消费节点最终合并的内存(需硬件 EDAC)、共模故障(需实现多样性)。

五、注意事项

  • 同一组内各角色的 integrity 设置应一致(默认全开即一致)。
  • 任务序号跨生产者须唯一:每次 onepath_xmr_submit 即一个独立任务实例;多生产者建议用 不同组。
  • onepath_xmr_get 内部对读取使用「查询全部副本 + 不合并应答」(对应 onepath_get_opts_ttarget = ONEPATH_QUERY_TARGET_ALLconsolidation = ONEPATH_CONSOLIDATION_NONE), 以便看到每个副本的应答用于投票。
  • 计算结果与存储值对 XMR 是不透明字节;编码 / 元信息请自行编排在值内。

API 参考

完整的函数签名、onepath_xmr_opts_t 选项字段、onepath_xmr_result_t 结构、回调类型与 ONEPATH_XMR_* 常量,见 多模冗余 XMR API

OnePath™ 是西安汉为信息技术有限公司的注册商标。