Beads Federation 实战指南:基于 Dolt Remotes 的多工作区对等同步
2026/9/12 16:43:05 网站建设 项目流程

Beads Federation 实战指南:基于 Dolt Remotes 的多工作区对等同步

【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads

Beads 的 Federation(联邦)机制利用 Dolt 的分布式版本控制能力,让多个工作区各自维护独立的 beads 数据库,同时通过配置的 peer(对等节点)双向同步 issue 数据。本指南以 docs/multi-agent/federation.md 为主线,结合bd federation命令族与存储层源码,完整讲解联邦的配置、peer 管理、同步策略、主权分级与跨副本租约治理,读完即可在独立团队或跨地域站点之间搭建一套无需中央服务器的 issue 同步网络。

概览:为什么需要 Federation

Federation 解决的是"多个独立团队或站点之间共享 issue 数据"的问题。与文件导出、导入不同,它直接复用 Dolt 的分布式版本控制能力,每个工作区保留自己的数据库,只把工作项增量同步给已配置的 peer。其核心收益包括:

  • Peer-to-peer(对等网络):无需中央服务器,每个站点(文档中称 town)自治运行;
  • 数据库原生版本化:同步基于 Dolt 的版本控制,而非文件导出;
  • 基础设施灵活:远端可选用 DoltHub、S3、GCS、本地路径或 SSH;
  • 数据主权分级:提供可配置的主权分级(T1–T4),满足 GDPR 等合规要求。

如果你只需要"两台机器通过一个自己拥有的对象存储桶共享同一个数据库",可以参考 Bucket Federation Quickstart 的端到端路径——它覆盖建桶、种子推送、第二副本诞生、同步节奏与故障模式,并给出了实测耗时。

前置条件

  1. Dolt 存储后端:联邦功能只支持 Dolt 后端,这是唯一受支持的存储后端。命令行的 Long 描述也明确写着"Requires the Dolt storage backend"(见 cmd/bd/federation.go)。此外,联邦命令要求对数据库的直接访问权限——proxied-server(代理服务器)模式下会直接拒绝执行(federation sync is not supported in proxied-server mode)。

配置联邦兼容的同步

编辑项目内的.beads/config.yaml,或用户全局的~/.config/bd/config.yaml

federation: remote: dolthub://myorg/beads # Primary remote (可选) sovereignty: T2 # 数据主权分级

也可以使用环境变量:

export BD_FEDERATION_REMOTE="dolthub://myorg/beads" export BD_FEDERATION_SOVEREIGNTY="T2"

在 docs/reference/configuration.md 的 Sync and Federation 一节中,这两个配置项被进一步细化:

  • federation.remote:Dolt 远端 URL,支持dolthub://org/beadsgs://bucket/beadss3://bucket/beadsaz://account.blob.core.windows.net/container/beadsfile://...等 scheme;
  • federation.sovereignty:数据主权分级 T1–T4(含义见下表);
  • federation.allowed-remote-patterns:用于限制允许的远端 URL 的 glob 模式列表,默认[]
  • federation.exclude_types:从联邦推送中排除的 issue 类型,默认[wisp]

bd config validate会校验远端 URL 格式、主权分级、federation.allowed-remote-patterns以及routing.mode。在 CLI 端,add-peer也支持--sovereignty标志(合法值为 T1、T2、T3、T4,输入会自动转为大写再校验,非法值直接报错)。

数据主权分级(Sovereignty Tiers)

分级描述适用场景
T1无限制(Full sovereignty,数据不离开受控基础设施)公开数据
T2组织级(Regional sovereignty,数据留在区域/司法管辖区)区域/公司合规
T3假名化(Provider sovereignty,数据托管于可信云厂商)移除标识符
T4匿名(No restrictions,数据可位于任何地方)最大隐私

添加联邦 Peer

使用bd federation add-peer注册远端 peer:

bd federation add-peer <name> <endpoint>

Peer 命名规则

  • 必须以字母开头;
  • 仅允许字母数字、连字符(-)和下划线(_);
  • 最大长度 64 字符。

支持的 Endpoint 格式

格式示例描述
DoltHubdolthub://org/repoDoltHub 托管的仓库
Google Cloudgs://bucket/pathGoogle Cloud Storage
Amazon S3s3://bucket/pathAmazon S3
本地file:///path/to/backup本地文件系统
HTTPShttps://host/pathHTTPS 远端
SSHssh://host/pathSSH 远端
Git SSHgit@host:pathGit SSH 简写

注意:add-peer的 Long 帮助中还支持一种直接连接 dolt sql-server的形式——host:port/database(如192.168.1.100:3306/beads),用于直连模式。

示例

# 在 DoltHub 上添加一个 staging 环境 bd federation add-peer staging dolthub://myorg/staging-beads # 添加云端备份 bd federation add-peer backup gs://mybucket/beads-backup bd federation add-peer backup-s3 s3://mybucket/beads-backup # 添加本地备份 bd federation add-peer local file:///home/user/beads-backup # 添加合作伙伴组织 bd federation add-peer partner-town dolthub://partner-org/beads

从源码看(cmd/bd/federation.go 的runFederationAddPeer),add-peer实际有两条注册路径:

  • 带凭证:提供--user时,构造storage.FederationPeer(含 Name、RemoteURL、Username、Password、Sovereignty),调用store.AddFederationPeer,凭证会落入加密存储(见下文"凭证管理");
  • 不带凭证:仅调用store.AddRemote(ctx, name, url),等价于git remote add

凭证管理

--user(可配合--password,否则交互式提示输入)配置的 peer,其 SQL 凭证会以AES-256 加密后存储在本地。同步时自动使用已存储的凭证:

bd federation add-peer town-gamma 192.168.1.100:3306/beads --user sync-bot

凭证加密的实现在 internal/storage/dolt/credentials.go 中:数据库旁会生成一个随机 32 字节的加密密钥(即 AES-256),存于federation_peers表的password_encrypted列中。该文件还包含migrateCredentialKeys迁移逻辑——将旧的、由数据库路径推导出的可预测密钥加密的密码,重新用随机密钥加密一遍,说明凭证体系经历了从"可推导密钥"到"随机密钥"的安全加固。加密密钥文件(federation credential key)会被bd init写入的.beads/.gitignore排除在版本控制之外。

JSON 输出

脚本化使用--json标志:

bd --json federation add-peer staging dolthub://myorg/staging-beads # {"added":"staging","url":"dolthub://myorg/staging-beads","has_auth":false,"sovereignty":""}

输出字段包括added(peer 名)、urlhas_auth(是否带凭证)、sovereignty(分级)。federation syncfederation statusfederation list-peersfederation remove-peer均支持--json,便于在定时任务或 CI 中做机器可解析的状态判断。

验证配置

列出已配置的 peer:

bd federation list-peers

与 Peer 同步

使用bd federation sync从 peer 拉取并向 peer 推送,bd federation status在不传输数据的前提下检查同步状态:

# 与所有 peer 同步 bd federation sync # 与指定 peer 同步 bd federation sync --peer town-beta # 处理冲突 bd federation sync --strategy theirs # 或 'ours' # 检查状态(ahead/behind、可达性、冲突) bd federation status bd federation status --peer town-beta

关键语义(均有源码佐证):

  • 不带--peersync会列出所有远端并把origin排除在外(if r.Name != "origin"),对其余每个 peer 逐一执行同步;status则包含全部远端;
  • --strategy只接受ourstheirs,其他值直接报错invalid strategy
  • 不带--strategy遇到合并冲突时,同步会暂停并报告冲突表,交由人工解决,绝不自动解析;
  • status会执行一次轻量 fetch来探测可达性并刷新 ahead/behind 数据(ds.Fetch失败即标记Unreachable),同时展示LocalAhead/LocalBehind提交数、LastSync时间与HasConflicts状态,还会提示本地的 pending changes 数量。

冲突处理的底层调用链

以 internal/storage/dolt/federation.go 的Sync实现为例,一次同步的完整流程是:

  1. 提交前自动提交commitBeforePull):同步开始前先把未提交的变更(含 config,其中kv.memory.*持久化记忆行位于其中)提交掉,否则 DOLT_MERGE 会以 "cannot merge with uncommitted changes" 失败——这是add-peer写入配置元数据后最容易踩的坑;
  2. Fetch:从 peer 拉取远端分支;
  3. Merge:合并peer/branch分支,得到冲突列表;
  4. 冲突处理:无策略时返回错误提示人工介入;有策略时对每个冲突字段调用ResolveConflicts,随后CommitMergeResolution提交解决结果(同样包含 config),并重算is_blocked——因为冲突的合并会跳过自动的 is_blocked 重算,必须在解决提交后补齐整个 merge+resolution 窗口;
  5. 推送:合并成功后把本地提交推回 peer。

拓扑模式(Topologies)

模式描述适用场景
Hub-spoke(星型)中心 hub,卫星节点同步到 hub需要中央协调的团队
Mesh(网状)所有 peer 两两互相同步去中心化协作
Hierarchical(层级)由多个 hub 组成的树多团队组织

架构原理

工作原理

  1. 每个工作区拥有自己的 Dolt 数据库;
  2. add-peer注册一个 Dolt 远端(类似git remote add);
  3. bd federation sync在 peer 之间推送和拉取提交;
  4. 冲突解决遵循配置的策略。

针对 Dolt SQL server 部署时,联邦使用两个端口:MySQL(3306)提供多写者 SQL 访问,remotesapi(8080)用于 peer 间的 push/pull:

┌─────────────────┐ ┌─────────────────┐ │ Workspace A │◄───────►│ Workspace B │ │ dolt sql-server│ sync │ dolt sql-server│ │ :3306 (sql) │ │ :3306 (sql) │ │ :8080 (remote) │ │ :8080 (remote) │ └─────────────────┘ └─────────────────┘

多仓库支持(Multi-Repo)

Issue 通过其SourceSystem字段标识由哪个联邦系统创建,从而在跨组织场景下建立正确的归属与信任链(该字段在 internal/storage/issueops/public_create.go 的克隆创建路径中随 issue 一并复制)。

连通性

远端连通性在首次 push/pull 操作时验证,而非添加 peer 时。因此你可以在基础设施就绪之前就完成 peer 配置——文档明确指出"Remote connectivity is validated on first push/pull operation, not when adding the peer"。

存储接口层

联邦能力通过internal/storage/versioned.go暴露的版本化存储接口与FederationStore接口(见 internal/storage/federation.go,含AddFederationPeer/GetFederationPeer/ListFederationPeers/RemoveFederationPeer)实现;Dolt 的具体实现位于 internal/storage/dolt/store.go 与 internal/storage/dolt/federation.go。

租约按副本生效(Leases are per-replica)

这是联邦部署中最容易出事故、也最需要理解透彻的部分。一次认领租约(bd ready --claim+bd heartbeat,由bd reclaim收割)只在授予它的那个副本上有意义leases表是克隆本地的,从不复制;跨桥传输的只有 claim 的可见性——issue 行上的status/assignee——而它在其他副本上的可见性最多滞后一个同步周期。

联邦部署必须同时满足两条规则:

  1. 宽限窗口 > 同步周期,且租约 TTL > 同步周期。若 TTL 或bd reclaim --older-than的宽限小于副本交换状态的节奏,跨桥判断就是无意义的:远端视图天生落后一个完整周期,那边的收割者会用比租约本身还旧的数据判断存活。bd reclaim默认宽限为租约 TTL 的 2 倍;请把 TTL(或宽限)提高到同步周期之上,永远不要为了迁就它们而缩短同步周期。
  2. 收割权属于授予副本。每个租约记录授予它的副本,bd reclaim会跳过其他副本授予的租约,并在 stderr 上点名报告。在雇佣了工人的那台机器上收割死掉的 worker。

守卫是 opt-in 的:为副本命名

守卫只在给副本命名后才生效:

export BEADS_NODE_ID=mini # 每台机器;或 bd config set node_id mini

node_id配置键由 cmd/bd/config.go 声明为"replica identity for the lease guard (read from yaml/env, never the DB)"。)

关于命名,两条规则都是承重的:

  • node_id命名的是 STORE(存储),不是主机。每个 beads数据库一个值。作为同一个dolt sql-server(BEADS_DOLT_SERVER_HOST、systemd/Docker 服务器、Hosted Dolt、VPS)的客户端的多个主机,无论多少台机器都是一个副本——给它们同一个值,或保持未设置。若给了不同 id,就会重建下述 fail-closed 回归:supervisor 匹配不到任何 worker 的租约,永远收割 0 个。只有存在真实的同步周期时,才为某个副本命名。
  • node_id是逐机器的,因此绝不能提交入库。项目内的.beads/config.yaml是 git跟踪的文件。一旦把node_id提交进去,一台机器的身份就会传播给所有克隆它的副本,然后所有比较都匹配:守卫"完全武装"却又"完全惰性",laptop会像收割本地租约一样收割mini的租约——这正是该特性要关闭的隐患,却在你以为受保护时发生。这比完全不设置更糟。因此bd config set node_id写入用户全局~/.config/bd/config.yaml,与其它逐机器状态(sync-state.jsonpush-state.jsonredirect)并列。请使用环境变量或该命令,永远不要手工把node_id加进.beads/config.yaml

刻意没有主机名回退

主机名回答的是错误的问题——它命名的是客户端进程的机器,而非存储。在那些最需要自动收割的拓扑里,猜主机名必然出错:共享或远程 dolt sql-server(BEADS_DOLT_SERVER_HOST、Hosted Dolt、VPS)下,多个主机是一个存储的客户端、彼此之间没有同步周期,按主机名分配身份会让 supervisor 收割不到任何 worker 的租约;容器里主机名是每次运行的容器 ID;macOS 的瞬态主机名跟随网络变化。这些都会在一个根本没有联邦的部署上把工作困死——比守卫要防止的失败更糟。

所以未设置身份时,行为降级为旧行为(每个租约都视为本地),而不是 fail-closed:升级以及任何单存储部署,永远不会困死收割者以前能恢复的租约。该特性落地前授予的租约同样不带副本标记,会一直保持可收割状态,直到某次 heartbeat 用已配置的 node 重新盖戳。

解除守卫:bd reclaim --any-replica

bd reclaim --any-replica解除守卫。它适用于永久消失的副本(或已被重命名、现在把自身旧租约视为外来的节点)——这不是常规设置,因为只有授予机器才对持有者是否存活有第一手视角。bd reclaim会把它拒绝的租约在 stderr 上一行总结;配合bd -v可展开到前 20 条租约明细。

heartbeat 证明存活,但不移动租约

普通 heartbeat 只在授予副本仍为空时回填它——不会覆盖一条明确命名了归属方的行。所以租约通常终身保留其授予副本,以下状态会困死一条正被本地 heartbeat 维持的租约:

  • 重命名的副本(minimini2)持续 heartbeat 自己的租约,而这些租约从此永远显示为外来;
  • 通过 JSONL 互操作流入的外来租约,其持有者名在本地也存在,于是在这里被 heartbeat,但仍带着远端节点标签;
  • 导入落到一条已过期的本地租约行上时,会连同授予副本一起整行采用快照——于是本节点自己的陈旧租约可能带着远端标签回归。

(唯一能让租约反向移动的路径是:heartbeat 的持有者是租约行持有者的不同拼写——它会通过 upsert 重新武装,盖上新节点戳。)

当确认授予副本不再收割后,可用bd reclaim --any-replica恢复被困租约。确认"授予副本不再收割"正是该守卫的全部意义,因此优先使用窄形式:对单个 issue 用bd reclaim --any-replica --id <id>,或bd unclaim --force <id>;裸的全局形式会回退所有外来陈旧租约,包括活着的 peer。bd reclaim会在 stderr 上点名它拒绝的内容——每次运行一条摘要,bd -v展开到前 20 条租约明细。

在 cmd/bd/reclaim.go 的帮助文本中,上述两条不变式(grace window > sync interval,且 lease TTL > sync interval)被明确标注为"守卫无法替你强制执行的"前提,并再次强调bd reclaim --any-replica是"override(覆盖开关),不是 scope(作用域)":它会加宽处理集合,越过每个副本的默认边界。

计划中的功能

以下操作已有基础设施支持,但尚未以命令形式暴露:

  • bd federation push <peer>/bd federation pull <peer>—— 与单个 peer 的单向同步。bd federation sync已覆盖双向场景。

故障排查

"requires direct database access"

联邦命令需要 Dolt 后端并提供直接数据库访问。请确保为联邦操作配置了 Dolt 后端(proxied-server 模式下联邦子命令会直接返回不支持)。

"peer already exists"

同名 peer 已存在。换一个名字,或先用bd federation list-peers查看现有 peer。

无效的 endpoint 格式

确保 endpoint 匹配上文列出的某种受支持格式。scheme 必须是:dolthub://gs://s3://file://https://ssh://,或 git SSH 格式(git@host:path);add-peer还支持直连形式host:port/database

一般健康检查

bd doctor --deep

参考

  • 全部联邦配置项:参见 Configuration 参考(federation.remotefederation.sovereigntyfederation.allowed-remote-patternsfederation.exclude_types及环境变量覆盖BD_FEDERATION_REMOTE/BD_FEDERATION_SOVEREIGNTY);
  • 命令实现:cmd/bd/federation.goadd-peer/remove-peer/list-peers/sync/status五个子命令,含--peer--strategy--user/--password--sovereignty--json标志);
  • 存储接口:internal/storage/versioned.go(版本化存储与Sync/SyncStatus/SyncResult)与internal/storage/federation.goFederationStore接口);
  • Dolt 实现:internal/storage/dolt/store.gointernal/storage/dolt/federation.go(Sync 完整流程)、internal/storage/dolt/credentials.go(AES-256 凭证加密与密钥迁移);
  • 租约守卫:cmd/bd/reclaim.go--any-replica--older-than--id与 stderr 报告语义);
  • 桶联邦快速入门:见 Bucket Federation Quickstart(bd syncbd federation sync的适用场景对比、退出码约定与实测成本)。

【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询