云端同步架构¶
背景:SPEC-004 Phase 3 要做"客户端众包 + 数据共享 + 贡献度"。这要求多类数据能高效增量同步到云端,不只是域名状态。 本文档解释为什么选 jsstore(IndexedDB)作为所有 sync-related 数据的统一存储,以及 Phase 3 的 store 设计预览。
1. 存储方案对比(云端协同视角)¶
| 能力 | chrome.storage.local | jsstore (IndexedDB) | Dexie |
|---|---|---|---|
| 增量 sync(只传变化的) | ❌ 要 diff 整 Object(~MB 级) | ✅ where: { syncedAt < lastSeen } 索引扫描(ms) |
✅ 内置 sync 扩展 |
| 批量按字段查询 | ❌ 全表 JS filter | ✅ where: { state } / where: { in: [...] } |
✅ |
| 加 sync 字段 | 改 schema 软(每个 key 各 own) | ✅ migrations 加列 | ✅ |
| 数据量上限 | ❌ 单 key 5MB / 总 10MB | ✅ GB 级 | ✅ 同 |
| 并发写(多 alarms 同时) | ❌ JSON 替换 race | ✅ transaction 隔离 | ✅ |
| 现有项目 fit | 简单 settings 用 | ✅ MapTaskData 已用 | ❌ 新 dep + 重构 |
选 jsstore(v0.10.94 起,DomainStats 是第 1 个 sync-related store)。
2. Phase 3 store 全景(已设计未实现)¶
按 SPEC-004 Phase 3.x 设计,云端协同需要至少 4 类数据:
2.1 DomainStats(v0.10.94 已实现)¶
// src/utils/jsstore/base.ts:tblDomainStats
{
domain: string (primary key)
state, recent[], fetchTotal, fetchOk, ..., firstSeen, lastSeen, stateChangedAt, stateExpiresAt,
// Phase 3 预留
syncedAt: number // 增量 sync where 字段
cloudConsensus: number // 0-1 N 客户端共识强度
}
- 用途:域名健康度记忆 + 跨用户共享(dead/antibot-hard 域名一致性高,云端聚合后下发)
- 量级:1-5k 域名 / 用户
- sync 频率:中频(每 N 分钟批量)
2.2 ContactPool(Phase 3.1)¶
{
urlHash: string (primary key) // sha256(normalized url)
domain: string // 索引(按域名批量查)
emails: string[]
phones: string[]
socials: { fb, ins, li, tw, yt, wa }
// 抓取来源(反作弊)
contributorCount: number
firstContributedAt: number
lastVerifiedAt: number
verifyTotal: number
verifyMatch: number // 数据一致性评分
// sync
syncedAt: number
cloudHash: string // 云端版本 hash(冲突检测)
}
- 用途:本地缓存的"已抓过的页面 contact",先查云端命中则直接用 — 不抓
- 量级:10w-100w URL / 用户(贡献者多)
- sync 频率:高频(每次抓完就 enqueue 上传)
2.3 CloudDomainState(Phase 3.2)¶
{
domain: string (primary key)
state: DomainState // 云端权威状态
consensus: number // 0-1 N 客户端共识强度
updatedAt: number
expiresAt: number // 云端 TTL
// 本地标记
fetchedAt: number // 本地最后拉云端的时间
}
- 用途:云端权威域名状态缓存(启动时拉一次,过期前用)
- 量级:1-5k
- sync 频率:低频(每小时拉一次)
2.4 ContributionLedger(Phase 3.4)¶
{
id: number (auto-increment)
userId: string
action: 'upload-new' | 'verify-match' | 'consume-query' | 'reset' | ...
earnedAt: number
amount: number // 贡献度变化(+/−)
ref: string // 关联 urlHash / domain
// sync
syncedAt: number
serverAcked: boolean // 服务端是否已记账
}
- 用途:贡献度账本(本地先入账 → 异步上传服务端 → 服务端 ack 后置 serverAcked=true)
- 量级:随用户行为,可能数千-数万条
- sync 频率:实时(每条 action 立即 enqueue)
3. 增量同步设计¶
3.1 通用 sync 流程(应用到 4 个 store)¶
本地写入 (saveStat / writeContact / writeLedger)
↓ 自动设 syncedAt=0(或保持 < lastSeen)
本地 syncer cron (每 N 秒/分钟)
↓
1. select where: syncedAt < lastSeen LIMIT 100
2. upload to cloud API
3. on success: update syncedAt = now
4. on conflict: pull cloud version + merge + retry
3.2 拉云端:CloudDomainState / ContactPool¶
启动时 + 每小时:
1. cloud GET /sync?since={localMaxUpdatedAt}
2. 批量 jsstore.insert(upsert) 覆盖本地
3. UI 自动用新数据
3.3 冲突解决¶
- DomainStats / ContactPool:last-write-wins(按 lastModified 时间戳)+ 云端共识算法(N 个客户端独立报告同结果 → 高置信度)
- ContributionLedger:append-only(不冲突,服务端 ack 即可)
4. v0.10.94 已做 / 待做¶
| 项 | 状态 | 说明 |
|---|---|---|
| DomainStats jsstore schema | ✅ v0.10.94 | base.ts tblDomainStats,version=3 |
| domain-state.ts 改用 jsstore | ✅ v0.10.94 | 旧 chrome.storage.local 数据自动迁移 |
syncedAt / cloudConsensus 字段 |
✅ 预留 | 暂不读写,Phase 3 启用 |
| ContactPool jsstore schema | ⏸ Phase 3.1 | 设计已有,未建表 |
| CloudDomainState jsstore schema | ⏸ Phase 3.2 | 设计已有 |
| ContributionLedger jsstore schema | ⏸ Phase 3.4 | 设计已有 |
| Sync API 客户端 | ⏸ Phase 3 | 服务端先就绪 |
| Sync API 服务端 | ⏸ Phase 3 | 业务决策后启动 |
5. 为什么不用 dexie / pouchdb¶
- Dexie + Dexie Cloud:sync 体验好,但是付费 / vendor lock。且需要把 MapTaskData 也迁移过去,重构成本高
- PouchDB + CouchDB:双向 sync 天然,但服务端栈是 CouchDB(项目当前栈是 Express + MySQL 等通用栈,不想为此引入新数据库)
- jsstore + 自建 sync API:现有 stack 一致 / 完全控制 / 学习成本零(已用 MapTaskData)。代价:自己实现增量 sync 逻辑(~1 周工程量)
6. 关键约束¶
所有 sync-related 数据必须:
- 用 jsstore 表(不要 chrome.storage.local)
- 加 syncedAt: number 字段(默认 0)
- enableSearch 在 sync 字段上(syncedAt, state, domain 等过滤字段)
- 单条 upsert(不要全表替换)
chrome.storage.local 留给: - settings(settingParams) - UI 偏好(zoom / theme) - 单 key 的小型状态(is_engine_running / lastForceReload 等) - watchdog / extension lifecycle 等无需 sync 的运行时状态
相关¶
- 域名状态机 — Phase 2 状态机详解(v0.10.93 起)
- SPEC-004-网站采集多阶段优化-云端协同 — Phase 3 完整方案
- 多阶段抓取pipeline — Phase 1 + 2 抓取架构
- 共享队列架构 — MapTaskData 调度(已 jsstore)