我为何创建 GenosDB:开箱即用的 P2P 数据库

发布: (2026年2月16日 GMT+8 01:05)
15 分钟阅读
原文: Dev.to

Source: Dev.to

(请提供需要翻译的正文内容,我将为您翻译成简体中文。)

P2P 数据库中的“最小核心”陷阱

你选择一个库是因为它看起来轻量。README 只展示了 3 行的设置。你想:完美,这就是我需要的全部。随后现实敲门。

  • 需要身份验证 → 另一个模块。
  • 需要真正可用的冲突解决 → 再来一个模块。
  • 加密? → 再来一个模块。
  • 不会损坏的离线持久化? → 祝你好运。

突然之间,你的“轻量”数据库变成了一个补丁式的插件集合,每个插件都有自己的怪癖、版本问题和未记录的边缘案例。

我在构建真实的 P2P 应用多年后深有体会,这也是我创建 GenosDB 的原因。

现有项目及其权衡

项目优势痛点
GunDB在 JavaScript 中开创了 P2P 数据库。• 核心基于 localStorage(同步、5 MB 上限、阻塞主线程)。
• 冲突解决使用墙钟时间戳(HAM),导致漂移且难以调试。
• 长时间断连后同步协议变得不可预测;缺乏干净的重放机制。
• 加密采用自定义实现(SEA),而非浏览器原生标准。
• 实际使用时需要堆叠多个模块(SEA 用于认证、RAD 用于存储、自定义中继用于信令),学习曲线陡峭且组合脆弱。
OrbitDB架构坚实:Merkle‑CRDT、追加日志、代码库整洁。• 需要 IPFS + Libp2p 作为依赖 → 这意味着你要采用完整的分布式网络栈,包含自己的守护进程、配置和运维复杂性。
• 对于仅需在网页应用中实现 P2P 数据同步的多数 JS 开发者来说,这是一项沉重的投入。

这两个项目都给了我灵感,但都没有满足我的需求:一个完整、可投入生产的 P2P 图数据库,从第一行代码即可使用,基于现代 Web 标准,且无需任何外部基础设施。

Source:

介绍 GenosDB

import { gdb } from "genosdb";

const db = await gdb("myapp", { rtc: true });

两行代码。 这就是背后已经在运行的内容。

存储 – OPFS + IndexedDB

GenosDB 使用 Origin Private File System (OPFS) ——一种现代的、沙箱化的文件系统 API。所有 I/O 都在专用的 Web Worker 中执行,主线程永不阻塞。

层级描述
同步 OPFS最低延迟,原子写入
异步 OPFS基于流的,仍然快速
IndexedDB通用回退方案

结果: GenosDB 会自动在任意浏览器中挑选最佳的存储方式 —— 没有大小限制,不会阻塞主线程,并且每个文件都有写入队列,防止并发操作导致的损坏。

同步引擎 – 双模式

模式工作原理
增量同步(主模式)每次变更都会记录在一个有上限的操作日志(oplog)中。当节点重新连接时,仅把缺失的操作使用 MessagePack 序列化、Pako 压缩后发送。带宽占用最小,延迟最低。
全状态回退(自动)如果节点离线时间过长,日志无法覆盖缺口,系统会自动发送整个压缩后的图状态。接收节点进行合并,重置时钟,并立即准备好进行后续的增量同步。

无需手动干预。没有破损状态。真正可用的最终一致性。

因果顺序 – 混合逻辑时钟

在分布式系统中,墙钟时间并不可靠。GenosDB 使用 Hybrid Logical Clocks (HLC) ——因果顺序的标准方案。每个操作都会获得唯一的、部分有序的时间戳,且不依赖同步的设备时钟。冲突通过 最后写入获胜 语义确定性地解决。

P2P 信令 – GenosRTC + Nostr 中继

GenosDB 的 P2P 模块(GenosRTC)使用 Nostr 中继 进行 WebRTC 信令。它自带一份稳定中继的内置列表,并会自动更新 —— 因此开箱即用,无需配置。开发者也可以自行提供中继列表,以满足私有网络或特定基础设施的需求。

中继管理具备智能特性:

  • 即时连接内置的稳定中继(零启动延迟)。
  • 并行地从本地缓存和社区来源(如 nostr.watch)加载额外中继。
  • 自动检测并剔除不健康的中继(需要工作量证明、超时、限制性策略等)。
  • 支持自定义中继 URL:
gdb("app", { rtc: { relayUrls: ["wss://my-relay.com"] } });

信令完成后,所有数据都通过 WebRTC 数据通道直接点对点传输 —— 服务器永远不触及你的数据。

多标签页同步

同一应用的多个标签页通过 BroadcastChannel 保持同步。不存在竞争条件,也不会出现标签页之间的陈旧数据。

紧凑序列化

所有数据——无论是磁盘上的还是网络传输中的——都使用 MessagePack(紧凑的二进制格式,比 JSON 更快)进行序列化,并通过 Pako(zlib)压缩。这大幅降低了存储占用和网络负载,相较于基于 JSON 的方案更为高效。

快速‑入门 API

import { gdb } from "genosdb";

const db = await gdb("myapp", { rtc: true });

// Create — returns a SHA‑256 content‑addressable ID
const id = await db.put({ name: "Alice", role: "admin" });

// Read
const node = await db.get(id);

// Read with real‑time subscription
db.get(id, (node) => {
  console.log("Node changed:", node);
});

// Update
await db.put({ name: "Alice", role: "superadmin" }, id);

// Delete (also cleans up all edges)
await db.remove(id);

// Graph relationships
await db.link(userId, projectId);

// Reactive query with MongoDB‑style filters
db.map(
  { where: { role: { $in: ["admin", "superadmin"] } } },
  (node, id, action) => {
    // action: 'initial' | 'added' | 'updated' | 'removed'
    console.log(action, id, node);
  }
);

// Graph traversal — follow edges recursively
db.map(
  {
    where: { type: "department" },
    $edge: { where: { active: true } },
  },
  (node, id) => {
    // Returns all active descendants of department nodes
    console.log("Descendant:", id, node);
  }
);

TL;DR

  • 最小化的核心 库往往会变成脆弱的拼凑。
  • GenosDB 为你提供 完整、可直接投入生产的 P2P 图数据库
  • 它利用现代 Web API(OPFS、Web Workers、WebRTC、BroadcastChannel)和成熟技术(HLC、MessagePack、Pako)。
  • 零外部基础设施,两行代码即可启动,且 API 简洁易用。

试一试,感受一下“轻量级”真正的 轻量级

排序和分页

db.map({
  where: { type: "post" },
  field: "created",
  order: "desc",
  $limit: 10,
  $after: lastCursorId
}, callback);

阻止来自对等方的删除操作

db.use(async (operations) => {
  return operations.filter(op => op.type !== 'remove');
});

在应用远程数据之前进行自定义验证

db.use(async (operations) => {
  return operations.filter(op => isValid(op));
});

在它触及本地数据库 之前,处理、验证、转换或拒绝传入的 P2P 数据。

GenosDB + P2P 层

GenosDB 不仅仅是数据库——它的 P2P 层支持对等方之间的直接通信。

命名数据通道

const chat = db.room.channel("chat");
chat.send({ text: "Hello!" });
chat.on("message", (msg, peerId) => { /* … */ });

音视频流

const stream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true
});
db.room.addStream(stream);
db.room.on("peer:stream", (stream, peerId) => { /* … */ });

对等方生命周期事件

db.room.on("peer:join",  (peerId) => { /* … */ });
db.room.on("peer:leave", (peerId) => { /* … */ });

构建协作应用、实时游戏、视频通话或文件共享——全部基于 P2P,全部使用同一个数据库实例。

模块化第一方特性

当你的应用规模扩大时,只激活你需要的功能。这些都是 第一方 模块(同一维护者,同一发布周期)。

const db = await gdb("myapp", {
  rtc: true,
  sm: { superAdmins: ["addr"] },   // Security: RBAC + WebAuthn + Mnemonic recovery
  nlq: true,       // Natural Language Queries
  geo: true,       // Geospatial ($near, $bbox)
  rx: true,        // Radix tree ($startsWith, prefix search)
  ii: true,        // Inverted index (full‑text search)
  audit: true      // Oplog auditing with custom prompts
});

SM(安全与管理)模块

  • WebAuthn – 生物识别或硬件密钥认证;在页面重新加载时静默恢复会话。
  • 助记词 (BIP‑39) – 友好的账户创建与恢复方式。
  • 加密身份 – 类似以太坊的密钥对;所有 P2P 操作均签名并验证。
  • RBAC 层级superadmin > admin > manager > user > guest(完全可自定义)。
  • 细粒度权限read, write, link, publish, delete, deleteAny, assignRole
  • 加密存储db.sm.put() / db.sm.get() 用于端到端加密、用户作用域的数据。
  • 角色过期 – 可为角色分配可选的 TTL(生存时间)。

这是我最引以为傲的创新之一;在 GenosDB 之前并不存在此功能。

Cellular Mesh – 可扩展的基于浏览器的 P2P

经典的平面网状拓扑(每个节点 ↔ 其他所有节点)在约 10 个节点后会崩溃(O(N²) 连接)。
GenosDB 引入 Cellular Mesh,一种将节点分组为逻辑单元并使用桥接节点进行单元间通信的覆盖协议:

cell‑0 ←→ cell‑1 ←→ cell‑2 ←→ cell‑3
  │          │          │          │
peers      peers      peers      peers
  • 仅限单元内连接 – 每个节点只与其所在单元中的节点通信。
  • 桥接节点 在单元之间转发消息,将连接复杂度从 O(N²) → O(N) 降低。

Cellular Mesh 特性

特性描述
动态单元大小随着网络变化,单元会自动增大或缩小。
基于健康评分的桥接选择桥接节点根据连接质量选择,而非随机。
基于 TTL 的传播消息 TTL 根据实际拓扑计算。
自动去重防止消息风暴。
心跳清理移除不活跃的节点。

据我所知,没有其他基于浏览器的 P2P 数据库或 WebRTC 框架实现类似功能。它源自对 OVGrid(一个行星级规模的虚拟世界)的扩展需求。

使用单个标志即可启用 Cellular Mesh:

{ rtc: { cells: true } }

仅浏览器实时示例

示例描述
协作白板点对点绘图画布
实时视频房间点对点视频流
协作富文本编辑器实时输入、远程光标、基于角色的访问控制、版本历史
安全去中心化笔记端到端加密、点对点共享笔记
位置共享使用 Leaflet + GenosRTC 的实时地图
物联网恒温器响应式点对点设备控制
蜂窝网格监控(3D)Three.js 可视化网格拓扑

查看全部示例 →

安装

npm

npm install genosdb
import { gdb } from "genosdb";
const db = await gdb("my-app", { rtc: true });

CDN

<script type="module">
  import { gdb } from "https://cdn.jsdelivr.net/npm/genosdb@latest/dist/index.min.js";
  const db = await gdb("my-app", { rtc: true });
</script>

两行代码。完整的 P2P 图数据库。无需编译。无需基础设施。无供应商锁定。

资源

  • 文档: https://github.com/estebanrfp/gdb
  • 白皮书 – GenosDB 设计与架构概览
  • 路线图 – 计划的功能与未来更新
  • 示例 – 代码片段与使用演示
  • API 参考 – 详细的方法文档
  • Wiki – 其他笔记与指南
  • GitHub 讨论 – 社区问答
  • 仓库 – 已压缩的生产就绪文件
  • 网站https://genosdb.org

关于作者

我叫 Esteban Fuster Pozzi@estebanrfp),是一名专注于 dWEB 研发的全栈开发者。我使用纯 JavaScript 构建分布式系统,因为网络应该是自由的、弹性的,并且归使用它的人所有。

本文是 GenosDB(GDB)官方文档的一部分。

0 浏览
Back to Blog

相关文章

阅读更多 »