131 lines
9.4 KiB
Markdown
131 lines
9.4 KiB
Markdown
# 数据保留与归档策略
|
||
|
||
Orbit 将保留策略作为命名空间级数据库配置保存。控制台保持单管理员模型,登录后打开“保留策略”即可查看和修改窗口;每次修改都要求上一版本号、幂等键和变更原因,前后值写入 `orbit_audit_events`。多个 Orbit 节点读取同一个 MySQL 版本,因此不会因为节点环境变量不同而产生不同清理边界。
|
||
|
||
首次安装和数据库策略尚未保存时使用部署默认值:幂等记录 90 天、任务历史 365 天、流程历史 365 天、事件日志 365 天、已确认交付 90 天、已处理 Inbox 90 天、管理审计 2555 天。默认 `enabled=false`,保存策略也不会立即删除数据。
|
||
|
||
环境变量只负责首次展示/未保存策略的默认值:
|
||
|
||
```text
|
||
ORBIT_RETENTION_IDEMPOTENCY_DAYS=90
|
||
ORBIT_RETENTION_TASK_DAYS=365
|
||
ORBIT_RETENTION_WORKFLOW_DAYS=365
|
||
ORBIT_RETENTION_EVENT_DAYS=365
|
||
ORBIT_RETENTION_DELIVERY_DAYS=90
|
||
ORBIT_RETENTION_INBOX_DAYS=90
|
||
ORBIT_RETENTION_AUDIT_DAYS=2555
|
||
```
|
||
|
||
窗口范围为 1–3650 天,幂等记录不得短于 90 天;所有节点应使用同一组默认值。数据库中已有策略后,环境变量不覆盖它。管理端的“允许导出只读归档”控制导出权限,导出仍须核对固定策略版本。
|
||
|
||
归档分两步:先用“预览”或 `GET /console/retention/preview` 查看各类候选,再按固定类别调用 `POST /console/retention/export` 分批生成只读 JSON 快照。每个快照包含冻结的策略版本、数据库时间、截止时间、根记录及关联历史,并返回 SHA-256;源表仍然保留,导出成功只记录摘要和数量审计,不代表可以删除。后续删除执行器必须在独立发布和备份恢复验收后接入,不能把导出接口当成删除接口。
|
||
|
||
候选筛选由服务端固定目录实现,浏览器不能提交表名或 SQL。终态任务必须没有未知效果、租约和流程所有权;流程必须终态且没有未结任务或未处理 Inbox;事件必须没有未确认交付或未处理 Inbox;交付只允许已确认记录;Inbox 只允许已处理且流程已终态记录;幂等记录需同时超过过期时间和窗口。审计单独使用审计窗口,普通清理不处理审计记录。未确认交付、未处理 Inbox、未知效果、进行中的任务/流程和有效幂等身份始终受保护。
|
||
|
||
控制台接口示例:
|
||
|
||
```sh
|
||
# 已登录控制台会话;浏览器通常直接使用页面,不需要手工传令牌
|
||
curl -b orbit-console.cookie http://127.0.0.1:8080/console/retention
|
||
curl -b orbit-console.cookie -X PUT http://127.0.0.1:8080/console/retention \
|
||
-H 'Content-Type: application/json' -H 'Idempotency-Key: retention-2026-q3' \
|
||
--data '{"expected_revision":"0","enabled":false,"idempotency_days":90,"task_history_days":365,"workflow_history_days":365,"event_log_days":365,"delivery_history_days":90,"inbox_history_days":90,"audit_log_days":2555,"reason":"初始生产保留评审"}'
|
||
```
|
||
|
||
## 管理页操作
|
||
|
||
1. 登录后打开 `/console/#/retention`,调整窗口、填写单行原因后保存;原因最多 1024 UTF-8 字节。幂等记录最少 90 天。
|
||
2. 点击“预览候选”:每类最多展示 100 条,`100+` 表示还有更多,并非全库总数。修改未保存时不能预览或导出,避免使用错误版本。
|
||
3. 需要导出时开启“允许导出只读归档”并保存,选择历史类型,点击“导出首批”。每批最多 20 条根记录,关联历史一并导出。浏览器需要 HTTPS 或 localhost 安全上下文来执行 SHA-256 校验。
|
||
4. 页面显示本批、累计条数和完整摘要;有后续记录时显示“导出下一批”,到末批后停止。可“重新下载本批”,切换历史类型或保存新策略会重置进度。“从首批开始”重新扫描,不会清理已下载文件。
|
||
|
||
下载文件保存 `format_version`、`sha256`、原始字符串 `content` 三个字段。页面关闭或刷新后内存中的分页进度会丢失;文件中的 `content.next_cursor` 可用于接口继续导出。服务端提交后网络中断可能多记录一次导出审计,但不改变任何源业务记录;页面未成功校验时不推进游标。修改策略的网络重试在当前页面复用原幂等键。
|
||
|
||
## 导出接口与分页
|
||
|
||
这些接口仅允许已登录控制台会话;业务 Bearer 凭据不能代替管理员会话。
|
||
|
||
| 接口 | 请求/结果 |
|
||
| --- | --- |
|
||
| `GET /console/retention` | `data` 为当前策略,`revision` 是字符串;未保存版本为 `"0"` |
|
||
| `PUT /console/retention` | 必填全部窗口、`enabled`、字符串 `expected_revision`、单行 `reason`,请求头必填 `Idempotency-Key`;幂等返回同一版本 |
|
||
| `GET /console/retention/preview` | `data.policy` 为所用策略,`sample_limit=100`;各类别包含 `kind/cutoff/count/more` |
|
||
| `POST /console/retention/export` | `kind`、字符串 `expected_revision` 必填;`limit` 默认 20、最大 100;`cursor` 默认空 |
|
||
|
||
响应采用标准 `{"data": ...}` 信封。导出请求示例:
|
||
|
||
```sh
|
||
curl -b orbit-console.cookie http://127.0.0.1:8080/console/retention/export \
|
||
-H 'Content-Type: application/json' \
|
||
--data '{"kind":"tasks","expected_revision":"1","limit":20}' \
|
||
--output export-response.json
|
||
```
|
||
|
||
`data.content` 是原始 JSON 文本,解析后包括:
|
||
|
||
| 字段 | 含义 |
|
||
| --- | --- |
|
||
| `policy` / `kind` | 本批实际策略与根记录类别 |
|
||
| `snapshot_at` / `cutoff` | 数据库读取时间与严格早于的候选截止时间,UTC |
|
||
| `source_retained` | 始终为 `true`,源数据保留 |
|
||
| `root_count` | 本批根记录数量,不含关联历史计数 |
|
||
| `tables` | 固定目录下的表与行;二进制为十六进制,整数和 JSON 正文按文本保留精度 |
|
||
| `next_cursor` | 非空表示可以继续;下一次请求原样传入相同 `kind` 和 `expected_revision` |
|
||
|
||
游标绑定命名空间、历史类型、策略版本与截止时间;不接受客户端表名或 SQL。策略变化后必须重新核对并从首批开始。每批使用独立数据库一致性快照,多个批次不是同一个全库时间点;期间从受保护状态转为候选的记录可能需要重新扫描。归档不是灾难恢复备份,不能直接把这些 JSON 导入生产库。
|
||
|
||
每个导出事务最多 10 秒、10000 条关联记录、8 MiB 正文;超限整体失败,不返回截断快照。减少根记录 `limit` 后可重新尝试;单个根记录本身过大时需要另行处理,不能忽略其历史。每次成功导出记录类别、策略版本、数量和摘要审计。
|
||
|
||
| 情况 | 处理 |
|
||
| --- | --- |
|
||
| 未登录/会话已失效 | 401,重新登录 |
|
||
| 归档关闭或策略版本不匹配 | 409,读取策略并重新核对 |
|
||
| 不支持的类别、游标不匹配、数量越界、快照超限 | 400,修正参数;超限时减小批量 |
|
||
| 修改策略结果不明 | 使用完全相同的内容和 `Idempotency-Key` 重试 |
|
||
|
||
离线核验及生成下一批请求(兼容控制台下载信封和上述 curl 响应):
|
||
|
||
```python
|
||
import hashlib
|
||
import json
|
||
from pathlib import Path
|
||
|
||
# 控制台下载文件也可替换这里的文件路径。
|
||
response = json.loads(Path("export-response.json").read_text(encoding="utf-8"))
|
||
snapshot = response.get("data", response)
|
||
assert snapshot["format_version"] == 1
|
||
content = snapshot["content"].encode("utf-8")
|
||
assert hashlib.sha256(content).hexdigest() == snapshot["sha256"], "快照校验失败"
|
||
page = json.loads(content)
|
||
assert page["source_retained"] is True
|
||
print("本批根记录:", page["root_count"])
|
||
if page["next_cursor"]:
|
||
Path("next-request.json").write_text(json.dumps({
|
||
"kind": page["kind"], "expected_revision": page["policy"]["revision"],
|
||
"limit": 20, "cursor": page["next_cursor"],
|
||
}), encoding="utf-8")
|
||
# 下一批:curl ... --data-binary @next-request.json --output export-response-2.json
|
||
```
|
||
|
||
摘要针对 `content` 的原始 UTF-8 字节,不对解析后重新格式化的 JSON 计算。SHA-256 用于发现内容损坏;摘要与正文一起被篡改时无法证明真实性,需要把审计摘要或外部签名另行保存在可信介质中。
|
||
|
||
## 只读盘点
|
||
|
||
`orbit-admin retention inventory` 用于在制定保留窗口、归档和备份恢复方案前盘点历史数据。它只执行带截止时间的统计查询,不删除、搬迁、改写数据,也不会自动判断某条记录可以安全归档。
|
||
|
||
```sh
|
||
ORBIT_MYSQL_DSN='user:password@tcp(127.0.0.1:3306)/orbit' \
|
||
go run ./cmd/orbit-admin retention inventory \
|
||
--before 2026-09-18T00:00:00Z
|
||
```
|
||
|
||
示例输出:
|
||
|
||
```json
|
||
{"cutoff":"2026-09-18T00:00:00Z","expired_idempotency":0,"terminal_tasks":0,"uncertain_tasks":0,"active_tasks":0,"terminal_workflows":0,"active_workflows":0,"acknowledged_deliveries":0,"unconfirmed_deliveries":0,"processed_inbox":0,"unprocessed_inbox":0,"events":0,"audit_events":0}
|
||
```
|
||
|
||
所有时间按 UTC 解析,严格早于 `--before` 的记录才计入。截止时间不能晚于数据库当前时间,避免把未来记录误认为历史。`terminal_tasks` 只统计确定终态且 `effect_uncertain=false` 的任务;`uncertain_tasks`、`active_tasks`、`active_workflows`、`unconfirmed_deliveries` 和 `unprocessed_inbox` 是需要先处理或保留的阻塞项。
|
||
|
||
结果是盘点快照,不是归档授权。真正的清理或归档还必须完成保留周期评审、未确认副作用核对、事件投递和流程推进核对、备份恢复演练、权限隔离及审计;当前命令没有 `apply` 或删除路径。
|