返回博客

Tuesday, August 5, 2025

【技术方案】离线优先的桌面应用云端数据同步

cover

1. 概要

离线优先的桌面应用与实时在线的 Web 应用协同工作,通过 Supabase 实现数据同步。

桌面应用端(Electron + Vue3 + SQLite)

  • 支持离线数据管理
  • 本地 SQLite 数据库存储
  • 用户认证(Supabase Auth)
  • 手动触发数据同步

Web 应用端(直接连接 Supabase)

  • 实时数据访问
  • 多终端即时同步
  • 基于 Supabase 行级安全(RLS)的权限控制

数据同步核心

  • 双向数据合并(Merge)
  • 冲突检测与解决
  • 增量同步优化

2. 注意点

  • Supabase 服务限制

    • 使用免费版,避免深度绑定
    • 仅使用 Auth 认证和 Table 存储功能
    • 不使用存储过程、函数等高级功能
  • 数据模型一致性

    • 所有终端必须保持数据模型版本一致
    • 同步协议需向前兼容
  • 安全约束

    • 桌面端需安全存储 Supabase 密钥
    • 行级安全策略(RLS)必须覆盖所有表
  • 离线场景

    • 桌面端需处理同步失败时的暂存数据
    • 冲突解决策略需考虑离线编辑的复杂性

3. 架构示意图

系统架构图

同步流程图


4. UUID 改造方案

4.1 数据库改造

SQLite 变更:

-- 原结构
CREATE TABLE PF_SUBJECT (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  ...
);

-- UUID 改造后
CREATE TABLE PF_SUBJECT (
  id TEXT PRIMARY KEY,  -- 存储 UUID
  ...
);

Supabase 变更:

CREATE TABLE "PF_SUBJECT" (
  "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  ...
);

4.2 应用层改造

1. ID 生成策略

// uuid 库方案(采用)
// 使用开源库生成完全符合 RFC4122 标准的 UUIDv4
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4(); // 例: '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
// Web Crypto API 方案(备用)
// 现代浏览器和 Electron 内置的标准化实现
// 使用 crypto API 生成 UUIDv4
const generateUUID = () => {
     return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
          const r = Math.random() * 16 | 0;
          const v = c === 'x' ? r : (r & 0x3 | 0x8);
          return v.toString(16);
     });
};

2. 数据操作适配

// 原代码
const recordId = 123; // number 类型

// 改造后
const recordId = 'd3b07384-d113-4ec6-8d67-61e5a678d6e3'; // string 类型

4.3 同步协议调整

{
  "device_id": "DESKTOP-001",
  "user_id": "auth0|12345",
  "sync_token": "20231005T083000",
  "changes": {
    "PF_SUBJECT": {
        "upsert": [
          {
            "id": "uuid1",
            "name": "数学",
            "_operation": "create",
            "_timestamp": 1696491000
          }
        ],
        "delete": ["uuid2"]
    }
  }
}

5. 关键设计决策

5.1 UUID 优势分析

优势说明
全局唯一彻底解决多用户 ID 冲突
离线生成桌面端可独立创建记录
简化同步无需 ID 映射逻辑
迁移友好避免复合主键复杂性

5.2 冲突解决策略

1. 时间戳优先

2. 业务特定规则

  • 数据:暂无

5.3 性能优化

  1. 批量处理
  • 每次同步最多 100 条记录
  • 使用 bulk insert 操作
  1. 增量同步
-- 桌面端查询
SELECT * FROM PF_SUBJECT 
WHERE updated_at > last_sync_time;
  1. 索引优化
CREATE INDEX idx_subject_updated ON PF_SUBJECT(updated_at);

6. 风险与应对

风险点应对措施
同步性能下降增加本地缓存层
UUID 存储空间增大使用压缩算法
旧数据迁移失败双轨并行过渡期
客户端兼容问题版本回退机制

7. 未来扩展