# Bync **Repository Path**: qwe12345678/Bync ## Basic Information - **Project Name**: Bync - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-18 - **Last Updated**: 2026-03-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Bync Bync 是一个面向 **Local-first** 应用的同步服务器(Sync Server / Sync Middleware),专注于在 **Bun** 运行时下提供高吞吐、低延迟的 **WebSocket + CRDT** 同步能力。 > 目标用户:使用 **Yjs** / **Automerge**(或其他 CRDT)构建协同白板、协作文档、多人笔记、看板等工具的团队。 > 核心卖点:把复杂的“后端同步逻辑 + 状态持久化 + 广播”变成开箱即用的基础设施。 --- ## 为什么需要 Bync? 越来越多的应用走向 **Local-first**(如 Linear、Logseq): - 客户端离线可用,体验更顺滑 - 多端同步自然发生 - 冲突合并交给 CRDT 自动解决 但痛点也非常明确: - **CRDT 同步**(状态向量、增量更新、广播、重放、幂等)后端实现复杂 - 通用后端组合(Node + MongoDB)在**二进制增量更新**场景下成本与性能并不理想 - 协作产品的核心链路(WebSocket + 广播 + 持久化)对吞吐与尾延迟极其敏感 Bync 的思路: - 利用 **Bun 的 WebSocket 高吞吐** - 利用 **Bun.Sqlite** 直接持久化 **binary Blob** - 提供面向 CRDT(Yjs/Automerge)的通用同步语义:订阅、拉取缺失更新、提交更新、广播、快照/压缩 --- ## 特性 - **毫秒级同步**:WebSocket 广播路径短、协议开销低 - **CRDT 适配层**: - `yjs` provider(内置) - `automerge` provider(内置) - 可扩展自定义 provider - **持久化优化**: - SQLite 存储二进制增量更新(Blob) - 支持快照(snapshot)与增量日志(update log) - 支持压缩(compaction)控制增长 - **房间/文档级广播**:同一文档的连接自动 fan-out - **可观测性**:内置指标与结构化日志(可接 Prometheus / OpenTelemetry) - **安全可选**:支持匿名(开发环境)或 Token/JWT(生产环境) --- ## 适用场景 - 协作文档 / Notion-like - 白板 / 画布 - 多人笔记 / 知识库 - 协同表格 / 表单构建器 - 任意 Local-first 应用(前端自己维护 CRDT 状态) --- ## 运行要求 - Bun(推荐最新稳定版) - SQLite(Bun 内置 Bun.Sqlite) --- ## 快速开始 ### 1) 安装 ```bash git clone https://github.com/your-org/bync.git cd bync bun install ``` ### 2) 配置环境变量 创建 `.env`: ```bash BYNC_HOST=0.0.0.0 BYNC_PORT=8787 # SQLite 文件路径 BYNC_DB_PATH=./data/bync.sqlite # provider: yjs | automerge BYNC_PROVIDER=yjs # 是否允许匿名访问(开发环境可开) BYNC_ALLOW_ANON=true # 生产环境建议配置(示例) BYNC_JWT_PUBLIC_KEY_PEM= BYNC_JWT_ISSUER= BYNC_JWT_AUDIENCE= # 可选:最大消息大小(字节) BYNC_WS_MAX_MESSAGE_SIZE=1048576 # 可选:内存中缓存的文档数量(LRU) BYNC_DOC_CACHE_SIZE=1000 ``` ### 3) 启动 ```bash bun run dev # or bun run start ``` 启动后: - HTTP 健康检查:`GET http://localhost:8787/healthz` - WebSocket 入口:`ws://localhost:8787/ws` --- ## 概念模型 Bync 的核心同步单位是 **Document**(文档)。你可以把它映射为: - 一篇文档 - 一张白板 - 一块画布 - 一个看板 - 任意需要多人协作的 CRDT 实例 **Document ID** 由客户端指定(字符串)。推荐结构化命名: - `org:{orgId}/space:{spaceId}/doc:{docId}` - `user:{userId}/note:{noteId}` --- ## WebSocket 协议(概览) Bync 采用“轻量控制帧 + provider 二进制 payload”的思路: - 控制帧:JSON(小) - CRDT 更新:binary(大) - 服务端只负责: - 鉴权(可选) - 房间管理 - 持久化(append log / snapshot) - 广播与补发 > 实际实现中可切换为 MsgPack/CBOR 等编码;本文档以 JSON 控制帧说明语义。 ### 1) 连接与鉴权 客户端连接到: ``` ws://{host}:{port}/ws ``` 可选鉴权方式(任选其一): - `Authorization: Bearer `(推荐) - `?token=`(便于调试,不推荐生产) ### 2) 加入文档(subscribe) 客户端发送: ```json { "t": "sub", "doc": "org:1/space:2/doc:abc", "provider": "yjs", "client": "web-123", "meta": { "app": "my-editor", "version": "1.0.0" } } ``` 服务端响应(示例): ```json { "t": "sub_ok", "doc": "org:1/space:2/doc:abc", "serverTime": 1730000000 } ``` 随后进入同步阶段。 --- ## 同步语义(按 provider) Bync 内置 provider 负责“如何计算缺失更新、如何合并、如何生成广播内容”。 ### A) Yjs(内置) 基本策略: - 客户端提交 `update`(binary) - 服务端将 update: 1) 追加写入 SQLite update log 2) 应用到内存中的 Y.Doc(缓存命中时) 3) 广播给同 doc 的其他连接 - 客户端初次加入时: - 客户端发送 `stateVector` - 服务端计算 diff update 并下发(或下发快照 + 增量) 控制帧(JSON): #### `y_state_vector` 客户端 -> 服务端: ```json { "t": "y_state_vector", "doc": "org:1/space:2/doc:abc" } ``` 随后客户端发送二进制帧(payload 为 Yjs state vector): - `binary: ` 服务端返回: - `t: y_sync_update` + binary update(缺失部分) ```json { "t": "y_sync_update", "doc": "org:1/space:2/doc:abc" } ``` 紧接一条 binary 帧(payload 为 `Y.encodeStateAsUpdateV2(serverDoc, stateVector)`)。 #### `y_update` 客户端 -> 服务端: ```json { "t": "y_update", "doc": "org:1/space:2/doc:abc" } ``` 紧接一条 binary 帧(payload 为 yjs update)。 服务端会: - `ack` 给发送者 - 广播给其他订阅者(同样以 `y_update` 控制帧 + binary) --- ### B) Automerge(内置) Automerge 生态存在不同同步层(如 automerge-repo)。Bync 提供“增量 changes + 可选快照”的通用同步: - 客户端提交 changes(binary / array) - 服务端持久化 changes,必要时生成快照 - 客户端加入时可请求快照或从 heads 处补齐 控制帧示例: - `a_pull`:请求从某个逻辑位置/heads 之后的 changes - `a_push`:提交 changes - `a_snapshot`:请求/下发快照 具体 wire 细节以 provider 实现为准(见 `PLAN.md` 的协议章节与代码注释)。 --- ## 数据存储(SQLite) Bync 采用 SQLite 存储: - 文档元数据(doc id、provider、版本、压缩点等) - 增量更新日志(Blob) - 快照(Blob) 优点: - 部署简单(单文件) - 写入延迟低 - Blob 友好,避免 MongoDB/JSON 序列化开销 - 易于备份/迁移 > 多实例/多机部署可在后续引入“外部 SQLite”或“日志分片 + 对象存储快照”方案(见 Roadmap)。 --- ## HTTP 接口 ### `GET /healthz` 返回: ```json { "ok": true } ``` ### `GET /metrics`(可选) Prometheus 文本格式指标(若启用)。 --- ## 权限与安全(建议) 生产建议: - 开启 JWT 校验(`BYNC_ALLOW_ANON=false`) - WebSocket 使用 TLS(WSS) - 按 doc 前缀做 ACL(例如 `org:{orgId}/...`) Bync 的权限模型(默认实现): - 解析 token 获取 `sub`(user id) - 根据 docId 解析出 orgId/spaceId - 调用可插拔的 `authorize(user, doc, action)` 决策: - `sub`(订阅/读取) - `push`(写入更新) - `presence`(可选) --- ## 性能与调优建议 - 增大 `BYNC_DOC_CACHE_SIZE` 可减少重建文档的成本(适合热点文档) - 设置合理的 `BYNC_WS_MAX_MESSAGE_SIZE` 防止异常 payload - 对高频写入 doc 启用更激进的 snapshot/compaction 策略 - 监控: - 每 doc 的连接数 - 每秒 update 数 - SQLite 写入耗时与 WAL checkpoint --- ## 项目结构(建议) ```text bync/ src/ server/ ws/ providers/ yjs/ automerge/ storage/ auth/ observability/ config/ scripts/ data/ README.md PLAN.md LICENSE ``` --- ## Roadmap(方向) - 多租户/命名空间隔离 - 细粒度 ACL 与审计日志 - 压缩与快照策略可配置(按 doc/按空间) - 多实例部署:一致性广播、共享存储或消息总线 - provider 生态:更多 CRDT/协议适配(如 Loro、Collabs 等) --- ## 贡献指南 欢迎提交 Issue / PR: - 新 provider 适配 - 性能压测与优化 - 存储与压缩策略改进 - 安全与鉴权增强 建议包含: - 复现步骤 - 预期/实际行为 - 最小可运行示例(如一个 Yjs demo) --- ## License MIT