mirror of
https://github.com/RaisFast/raisfast.git
synced 2026-09-24 00:02:28 +00:00
393 lines
14 KiB
Markdown
393 lines
14 KiB
Markdown
# 云备份服务设计
|
||
|
||
> raisfast Cloud Backup — 私有化数据的安全网
|
||
>
|
||
> 定位:**零配置、端到端加密、增量备份的云端备份服务**
|
||
|
||
---
|
||
|
||
## 1. 为什么需要这个功能
|
||
|
||
| 场景 | 后果 | 用户心理 |
|
||
|---|---|---|
|
||
| 硬盘损坏 | 所有客户数据丢失 | "我用私有化就是为了安全,结果数据反而丢了?" |
|
||
| 误删数据 | 重要商机/联系人丢失 | "有没有办法恢复?" |
|
||
| 勒索病毒 | 数据被加密,无法恢复 | "我愿意花钱恢复数据" |
|
||
| 服务器故障 | 业务中断 | "备份在哪里?" |
|
||
| 迁移新机器 | 需要手动复制数据 | "能不能一键迁移?" |
|
||
|
||
**私有化用户最大的焦虑 = 数据丢失没有兜底。** 解决这个焦虑 = 核心卖点 + 商业化入口。
|
||
|
||
---
|
||
|
||
## 2. 设计目标
|
||
|
||
| 目标 | 说明 |
|
||
|---|---|
|
||
| **零配置** | 注册账号 → 自动备份,不需要配置 S3/Azure |
|
||
| **端到端加密** | 数据在客户端加密,云端只存密文,服务端无法解密 |
|
||
| **增量备份** | 只传输变更部分,节省带宽和时间 |
|
||
| **版本历史** | 保留 N 个历史版本,支持回滚到任意时间点 |
|
||
| **自动调度** | 每小时/每天自动备份,无需手动操作 |
|
||
| **跨平台** | 桌面应用 + 服务器都支持 |
|
||
| **一键恢复** | 选一个版本 → 一键恢复到任意设备 |
|
||
|
||
---
|
||
|
||
## 3. 技术架构
|
||
|
||
### 3.1 整体流程
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 用户设备(客户端) │
|
||
│ │
|
||
│ SQLite DB → 变更检测 → 增量计算 → AES-256加密 → 压缩 │
|
||
│ ↓ │
|
||
│ 上传到备份服务器 │
|
||
│ ↓ │
|
||
│ 备份记录(本地) ← 备份元数据 ← 备份服务器确认 │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
↓ 加密数据上传
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 备份服务器(云端) │
|
||
│ │
|
||
│ 接收加密块 → 存储到对象存储(S3/R2)→ 记录元数据 │
|
||
│ │
|
||
│ 存储内容: │
|
||
│ ├── 用户账号信息(邮箱、设备列表) │
|
||
│ ├── 备份元数据(时间、大小、版本号) │
|
||
│ └── 加密数据块(AES-256-GCM,服务端无法解密) │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 3.2 端到端加密方案
|
||
|
||
```
|
||
密钥层级:
|
||
|
||
用户密码
|
||
↓ Argon2id
|
||
主密钥 (Master Key)
|
||
↓ HKDF-SHA256
|
||
├── 数据加密密钥 (DEK) → 加密备份数据
|
||
├── 密钥加密密钥 (KEK) → 加密存储 DEK
|
||
└── 文件名加密密钥 (FEK) → 加密备份文件名
|
||
|
||
流程:
|
||
1. 注册时:用户密码 → Argon2id → 主密钥
|
||
2. 备份时:主密钥 → HKDF → DEK → AES-256-GCM 加密数据
|
||
3. 上传时:只传密文,服务端看不到明文
|
||
4. 恢复时:密码 → 重新派生主密钥 → 解密
|
||
|
||
安全保证:
|
||
- 服务端被黑客入侵 → 无法解密(没有用户密码)
|
||
- 备份文件泄露 → 无法解密(AES-256-GCM)
|
||
- 用户忘记密码 → 无法恢复(零知识架构)
|
||
```
|
||
|
||
### 3.3 增量备份方案
|
||
|
||
```
|
||
SQLite WAL 模式:
|
||
|
||
首次备份(全量):
|
||
SQLite 文件 → 分块(4MB/块)→ 每块计算 SHA-256 → 加密 → 上传
|
||
|
||
后续备份(增量):
|
||
1. 对比当前块 SHA-256 与上次备份的块列表
|
||
2. 只上传 SHA 变化的块
|
||
3. 生成新的快照清单(指向块列表)
|
||
|
||
快照 A(全量): [block-1, block-2, block-3, block-4]
|
||
快照 B(增量): [block-1, block-2, block-3-new, block-4]
|
||
↑ 只有这个变了
|
||
|
||
存储开销:每次增量只存变化的块(通常 < 1MB)
|
||
```
|
||
|
||
### 3.4 SQLite 备份具体实现
|
||
|
||
```
|
||
方案选择:SQLite Backup API(sqlite3_backup_init)
|
||
|
||
Step 1: 创建临时 SQLite 副本
|
||
→ 使用 SQLite Backup API 将热数据库复制到临时文件
|
||
→ 确保数据一致性(不锁库)
|
||
|
||
Step 2: 计算块哈希
|
||
→ 临时文件按 4MB 分块
|
||
→ 计算每块 SHA-256
|
||
|
||
Step 3: 增量对比
|
||
→ 与上次备份的块列表对比
|
||
→ 识别变化的块
|
||
|
||
Step 4: 加密 + 压缩
|
||
→ 变化的块 → zstd 压缩 → AES-256-GCM 加密
|
||
|
||
Step 5: 上传
|
||
→ 加密块上传到备份服务器
|
||
→ 生成新快照清单
|
||
|
||
Step 6: 清理
|
||
→ 删除临时文件
|
||
→ 保留本地备份元数据
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 备份服务端设计
|
||
|
||
### 4.1 技术选型
|
||
|
||
| 组件 | 选型 | 说明 |
|
||
|---|---|---|
|
||
| 备份服务器 | Rust (Axum) | 与 raisfast 同技术栈,可独立部署 |
|
||
| 对象存储 | Cloudflare R2 | 免出站流量,S3 兼容 |
|
||
| 用户认证 | JWT | 简单可靠 |
|
||
| 数据库 | PostgreSQL | 存储用户/元数据 |
|
||
| 支付 | Stripe | 国际通用 |
|
||
|
||
### 4.2 API 设计
|
||
|
||
```
|
||
认证:
|
||
POST /api/v1/auth/register # 注册(邮箱+密码)
|
||
POST /api/v1/auth/login # 登录
|
||
POST /api/v1/auth/token # 刷新 Token
|
||
|
||
设备管理:
|
||
GET /api/v1/devices # 列出设备
|
||
POST /api/v1/devices # 注册设备
|
||
DELETE /api/v1/devices/:id # 移除设备
|
||
|
||
备份:
|
||
POST /api/v1/backups/upload # 上传备份块
|
||
POST /api/v1/backups/snapshot # 创建快照
|
||
GET /api/v1/backups/snapshots # 列出快照
|
||
GET /api/v1/backups/snapshots/:id # 获取快照详情
|
||
DELETE /api/v1/backups/snapshots/:id # 删除快照
|
||
|
||
恢复:
|
||
POST /api/v1/backups/restore/:id # 获取恢复所需的块列表
|
||
GET /api/v1/backups/blocks/:hash # 下载指定块
|
||
|
||
订阅:
|
||
GET /api/v1/subscription # 当前订阅状态
|
||
POST /api/v1/subscription/checkout # Stripe Checkout
|
||
POST /api/v1/subscription/webhook # Stripe Webhook
|
||
```
|
||
|
||
### 4.3 数据模型
|
||
|
||
```sql
|
||
-- 用户
|
||
CREATE TABLE users (
|
||
id UUID PRIMARY KEY,
|
||
email TEXT UNIQUE NOT NULL,
|
||
password_hash TEXT NOT NULL, -- Argon2id
|
||
created_at TIMESTAMPTZ NOT NULL
|
||
);
|
||
|
||
-- 设备
|
||
CREATE TABLE devices (
|
||
id UUID PRIMARY KEY,
|
||
user_id UUID REFERENCES users(id),
|
||
name TEXT NOT NULL, -- "MacBook Pro" / "Server-01"
|
||
device_key TEXT NOT NULL, -- 设备公钥指纹
|
||
created_at TIMESTAMPTZ NOT NULL
|
||
);
|
||
|
||
-- 备份快照
|
||
CREATE TABLE snapshots (
|
||
id UUID PRIMARY KEY,
|
||
device_id UUID REFERENCES devices(id),
|
||
snapshot_no BIGINT NOT NULL, -- 快照序号
|
||
size_bytes BIGINT NOT NULL, -- 原始大小
|
||
block_count INT NOT NULL, -- 块数量
|
||
created_at TIMESTAMPTZ NOT NULL
|
||
);
|
||
|
||
-- 备份块(去重)
|
||
CREATE TABLE blocks (
|
||
hash TEXT PRIMARY KEY, -- SHA-256
|
||
size_bytes INT NOT NULL,
|
||
storage_key TEXT NOT NULL, -- S3/R2 对象键
|
||
created_at TIMESTAMPTZ NOT NULL
|
||
);
|
||
|
||
-- 快照 → 块映射
|
||
CREATE TABLE snapshot_blocks (
|
||
snapshot_id UUID REFERENCES snapshots(id),
|
||
block_hash TEXT REFERENCES blocks(hash),
|
||
block_index INT NOT NULL, -- 块序号
|
||
PRIMARY KEY (snapshot_id, block_index)
|
||
);
|
||
|
||
-- 订阅
|
||
CREATE TABLE subscriptions (
|
||
id UUID PRIMARY KEY,
|
||
user_id UUID REFERENCES users(id),
|
||
plan TEXT NOT NULL, -- free/pro/enterprise
|
||
storage_limit BIGINT NOT NULL, -- 存储上限(字节)
|
||
stripe_id TEXT, -- Stripe 订阅 ID
|
||
status TEXT NOT NULL, -- active/canceled
|
||
created_at TIMESTAMPTZ NOT NULL
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 客户端集成
|
||
|
||
### 5.1 桌面应用集成
|
||
|
||
```
|
||
设置页面:
|
||
┌─────────────────────────────────────────────┐
|
||
│ 云备份设置 │
|
||
│ │
|
||
│ 账号:chris@example.com [登录/注册] │
|
||
│ 状态:✅ 已连接 上次备份:3 分钟前 │
|
||
│ │
|
||
│ 备份频率: │
|
||
│ ○ 每小时 ● 每天 ○ 每周 │
|
||
│ │
|
||
│ 备份历史: │
|
||
│ ┌─────────────────────────────────────────┐ │
|
||
│ │ 2024-04-23 14:30 12.5 MB [恢复] [删除]│ │
|
||
│ │ 2024-04-22 14:30 12.3 MB [恢复] [删除]│ │
|
||
│ │ 2024-04-21 14:30 11.8 MB [恢复] [删除]│ │
|
||
│ └─────────────────────────────────────────┘ │
|
||
│ │
|
||
│ 恢复到其他设备: │
|
||
│ [选择快照] → [生成恢复码] → 在新设备输入恢复码 │
|
||
│ │
|
||
│ [立即备份] │
|
||
└─────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.2 CLI 集成
|
||
|
||
```bash
|
||
# 登录
|
||
rust-backup login --email chris@example.com
|
||
|
||
# 手动备份
|
||
rust-backup backup --project ./my-project
|
||
|
||
# 查看备份历史
|
||
rust-backup snapshots --project ./my-project
|
||
|
||
# 恢复到指定版本
|
||
rust-backup restore --snapshot abc-123 --output ./restored-project
|
||
|
||
# 恢复到新设备(使用恢复码)
|
||
rust-backup restore --code ABCD-1234-EFGH-5678 --output ./my-project
|
||
|
||
# 生成恢复码(在其他设备上使用)
|
||
rust-backup recovery-code --snapshot abc-123
|
||
```
|
||
|
||
### 5.3 Plugin API(可在插件中触发备份)
|
||
|
||
```javascript
|
||
// 在插件中触发备份(如创建重要数据后)
|
||
Plugin.on_content_created = function(input) {
|
||
const data = parseBody(input);
|
||
if (data.content_type === "deal" && data.stage === "closed_won") {
|
||
// 赢单后自动备份
|
||
Host.backup();
|
||
}
|
||
return ok(data);
|
||
};
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 定价
|
||
|
||
| 套餐 | 存储空间 | 保留版本 | 设备数 | 价格 |
|
||
|---|---|---|---|---|
|
||
| **免费** | 1 GB | 7 天 | 1 台 | $0 |
|
||
| **Pro** | 50 GB | 90 天 | 5 台 | **$9.9/月** |
|
||
| **Team** | 500 GB | 365 天 | 无限 | **$29/月** |
|
||
| **Enterprise** | 无限 | 无限 | 无限 | **$99/月** |
|
||
|
||
### 6.1 成本估算
|
||
|
||
| 项目 | 单价 | 1000 个 Pro 用户成本 |
|
||
|---|---|---|
|
||
| Cloudflare R2 存储 | $0.015/GB/月 | $750(50GB × 1000 × $0.015) |
|
||
| R2 上传(Class A 操作) | $4.50/百万次 | ~$50 |
|
||
| R2 下载(恢复) | 免费(R2 无出站费) | $0 |
|
||
| 服务器(1 台) | $20/月 | $20 |
|
||
| **总成本** | | **~$820/月** |
|
||
| **收入** | $9.9 × 1000 | **$9,900/月** |
|
||
| **利润率** | | **~92%** |
|
||
|
||
---
|
||
|
||
## 7. 开发路线
|
||
|
||
### Phase 1 — 核心备份(1-2 月)
|
||
|
||
| 任务 | 说明 |
|
||
|---|---|
|
||
| 备份服务端 | Rust + Axum,用户注册/登录/上传/下载 |
|
||
| 端到端加密 | AES-256-GCM + Argon2id 密钥派生 |
|
||
| 增量备份引擎 | SQLite 分块 + SHA-256 对比 + zstd 压缩 |
|
||
| 桌面应用集成 | 设置页面 + 自动调度 + 状态显示 |
|
||
| CLI 命令 | `rust-backup login/backup/restore` |
|
||
|
||
### Phase 2 — 恢复体验(2-3 月)
|
||
|
||
| 任务 | 说明 |
|
||
|---|---|
|
||
| 一键恢复 | 选择快照 → 一键恢复 |
|
||
| 恢复码 | 跨设备恢复(类似恢复短语) |
|
||
| 版本对比 | 对比两个快照的差异 |
|
||
| 选择性恢复 | 只恢复特定表/数据 |
|
||
|
||
### Phase 3 — 高级功能(3-6 月)
|
||
|
||
| 任务 | 说明 |
|
||
|---|---|
|
||
| 团队功能 | 多设备管理、团队共享备份 |
|
||
| Point-in-time | 恢复到精确时间点 |
|
||
| 备份监控 | 备份失败告警、异常检测 |
|
||
| 合规报告 | 备份报告生成(企业审计用) |
|
||
|
||
---
|
||
|
||
## 8. 商业价值
|
||
|
||
### 8.1 为什么备份服务是最佳商业化入口
|
||
|
||
| 优势 | 说明 |
|
||
|---|---|
|
||
| **刚需** | 每个私有化用户都需要备份 |
|
||
| **持续付费** | 按月/年订阅,不是一次性购买 |
|
||
| **高粘性** | 备份数据在云端,用户不会轻易离开 |
|
||
| **高利润率** | 存储成本极低(~8%),利润率 90%+ |
|
||
| **信任入口** | 用户把数据交给你备份 → 建立信任 → 后续卖更多服务 |
|
||
| **天然获客** | 桌面应用内提示"开启云备份" → 零成本转化 |
|
||
|
||
### 8.2 与主产品的协同
|
||
|
||
```
|
||
raisfast 开源版(免费)
|
||
↓ 用户使用,积累数据
|
||
↓ 看到备份提示
|
||
rust-backup 云备份(付费)
|
||
↓ 用户付费备份
|
||
↓ 建立信任
|
||
↓ 推荐其他付费服务
|
||
raisfast 企业插件包(付费)
|
||
raisfast 行业模板包(付费)
|
||
raisfast 技术支持(付费)
|
||
```
|
||
|
||
**备份是整个商业化飞轮的起点。**
|