高可用与灾备 (HA + DR)
V1 内测期对单点故障的容忍度低 — 单 region / 单进程 / 没备份 = 灾难。 本页给三档 HA / DR 配置。
三档配置
档 A:MVP(单 region 单进程)
us-east-1 ├─ 1 Agent 进程(systemd / Docker) ├─ 1 PG instance └─ 1 私钥备份(自动到 cold store)| 维度 | 指标 |
|---|---|
| RPO | 24h(每日 PG snapshot) |
| RTO | 30 min(手动恢复) |
| 单点故障容忍 | ❌ 任一组件挂 = 服务中断 |
| 适合 | < 100 用户 / 内部使用 |
| 月成本 | < $50 |
档 B:标准(多 replica 单 region + 异地备份)
us-east-1 ├─ 3 Agent replica (k8s) ← 共享私钥 + 业务 PG ├─ Postgres primary + 1 read replica ├─ Redis(artifact / session 状态) └─ 每日 + WAL 增量备份 → S3 us-west-2
us-west-2 (待启用) └─ 备份 + DR runbook(暂不跑实例)| 维度 | 指标 |
|---|---|
| RPO | 5 min(WAL 增量) |
| RTO | 1h(手动从 backup 起 us-west-2) |
| 单点故障容忍 | ✓ Agent / PG read 挂仍服务 |
| 适合 | 1k-10k 用户 / 业务关键 |
| 月成本 | $200-500 |
档 C:高可用(双 region active-active + 跨 region replica)
us-east-1 (active) us-west-2 (active) ├─ Hashee Agent ×3 replica ├─ Hashee Agent ×3 replica └─ PG primary └─ PG read replica(streaming)
DNS / LB 按用户位置就近路由PG primary failover 用 Patroni / Pglook| 维度 | 指标 |
|---|---|
| RPO | < 1s(streaming replication) |
| RTO | < 5 min(auto failover) |
| 单点故障容忍 | ✓ 单 region 挂仍服务 |
| 适合 | 10k+ 用户 / 严苛 SLA |
| 月成本 | $1000+ |
Agent 进程的多 replica
利用 Hashee “3 并发连接上限” 做 HA:
# k8s deploymentreplicas: 3strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 03 replica 共享同一组 X25519 + Ed25519 私钥(k8s secret),共享业务 PG / Redis。 Hashee 后端 DeliveryShardDO 自动 hash 路由消息到不同 replica。
详见 自托管 VPS §“零停机重启”。
PG 备份
每日 base + WAL(推荐)
# 每日 base backup(cron 02:00)pg_basebackup -D /backup/base-$(date +%Y%m%d) -F tar -z -P
# WAL streaming(持续)# postgresql.conf:# wal_level = replica# archive_mode = on# archive_command = 'aws s3 cp %p s3://my-bucket/wal/%f'Neon / Cloud Postgres 用户
Neon / Supabase / AWS RDS / GCP Cloud SQL 全部内建 point-in-time recovery (PITR)。 RPO 通常 5 分钟。在 dashboard 启用即可。
灾备演练
每季度跑一次:
- 在 staging 模拟 us-east-1 整个 down
- 从 us-west-2 备份恢复 PG(或激活 read replica → promote)
- 在 us-west-2 启动 Agent 进程(拉同一份 secret)
- 验证:
- Agent 能连接 Hashee 后端
- 业务消息能收发
- DB 数据无丢失(按 RPO 期望验证)
- 记录 RTO 实测(vs 目标)
私钥灾备
最严重的灾难是私钥丢失。两层 + 跨 region:
| 备份 | 位置 | 用 |
|---|---|---|
| 热备(自动) | AWS Secrets Manager / Vault / wrangler secret | 部署 |
| 冷备(人工) | 1Password / Bitwarden / 纸面保险箱 | 灾难恢复 |
| 跨 region 复制 | hot 备份自动跨 AZ;cold 备份地理多点 | 双重保险 |
配置 in git,secret in secret store
| 项 | 位置 |
|---|---|
| 代码 + Dockerfile | git |
| infra (k8s YAML / Terraform) | git |
| 配置 (logger / Sentry DSN / 等) | git |
| 私钥 / token / DB password | secret store |
.env.example | git(含示例值) |
任何机器丢失能从 git + secret store 重建。
监控 + alerting
| 指标 | 严重度 | 阈值 |
|---|---|---|
| Agent connection status != connected | P1 | > 5 min |
| PG primary down | P0 | > 1 min |
| Backup 失败 | P1 | > 24h 无新 backup |
| Replication lag | P2 | > 60s |
| Disk usage | P2 | > 80% |
| LLM API 故障率 | P1 | > 5% over 5 min |
接 PagerDuty / Opsgenie / 24h oncall。
业务侧的”幂等” 约定
灾备恢复后可能重复 deliver 部分消息 → 业务侧必须幂等:
agent.addMessageHandler(async (msg) => { // SDK 已自动按 message_id 去重,但业务侧再加一层 const seen = await db.query("SELECT 1 FROM processed_messages WHERE message_id = $1", [msg.message_id]); if (seen.rows.length > 0) return; await db.query("INSERT INTO processed_messages (message_id, processed_at) VALUES ($1, NOW())", [msg.message_id]); // 业务处理});相关页面
- 部署 — 自托管 VPS — k8s 配置
- Production Checklist — 备份与灾备
- 信任中心 — Hashee 平台 SLA + status page