# ADR-007: 資料保留策略 > **狀態**: 已接受 > **日期**: 2026-03-20 > **決策者**: CEO, CTO, CIO --- ## 背景 需要定義各類型資料的保留時間 (TTL),確保: 1. 系統效能不因資料累積而下降 2. 重要資料有足夠的回溯時間 3. 儲存成本可控 ### CEO 指示 #7 > 熱資料 (Redis/即時查詢) TTL 7 天 => 初期是否也保留 6 個月?要確認數據量有多大? --- ## 決策 ### 資料分層策略 ``` ┌─────────────────────────────────────────────────────────┐ │ Layer 1: 熱資料 (Redis) │ │ TTL: 7-30 天 │ │ 用途: 即時查詢、快取、Session │ │ 預估容量: ~500MB │ └─────────────────────────────────────────────────────────┘ │ 過期後 ▼ ┌─────────────────────────────────────────────────────────┐ │ Layer 2: 溫資料 (PostgreSQL) │ │ TTL: 6 個月 (CEO 指示) │ │ 用途: 歷史查詢、報表、分析 │ │ 預估容量: ~5GB/月 │ └─────────────────────────────────────────────────────────┘ │ 過期後 ▼ ┌─────────────────────────────────────────────────────────┐ │ Layer 3: 冷資料 (歸檔) │ │ TTL: 永久 (審計日誌) / 1 年 (一般) │ │ 用途: 合規、稽核、法律要求 │ │ 預估容量: ~10GB/年 │ └─────────────────────────────────────────────────────────┘ ``` ### 各資料類型 TTL 定義 #### Redis 熱資料 (Layer 1) | 資料類型 | TTL | 說明 | 預估大小 | |---------|-----|------|---------| | Session Token | 7 天 | 用戶登入狀態 | ~1KB/session | | Dashboard 快取 | 5 分鐘 | 即時指標聚合 | ~10KB | | 主機狀態快取 | 30 秒 | 即時健康狀態 | ~2KB/host | | AI 回應快取 | 1 小時 | 相同問題快取 | ~5KB/entry | | 限流計數器 | 1 分鐘 | Rate Limiting | ~100B/user | **Redis 容量評估**: - 4 台主機 × 2KB = 8KB (即時狀態) - 100 用戶 × 1KB = 100KB (Session) - Dashboard 快取 = 50KB - AI 快取 (1000 條) = 5MB - **總計: ~10MB (遠低於 Redis 16GB 容量)** > ✅ **結論**: Redis 熱資料保持短 TTL (7-30 天) 是合理的,不需要延長至 6 個月。 > Redis 用於快取和即時查詢,歷史資料應存放在 PostgreSQL。 #### PostgreSQL 溫資料 (Layer 2) | 資料類型 | TTL | 說明 | 預估大小 | |---------|-----|------|---------| | 監控指標 | 6 個月 | CPU/Memory/Disk 歷史 | ~1GB/月 | | 告警記錄 | 6 個月 | 歷史告警 | ~100MB/月 | | 部署記錄 | 6 個月 | Pipeline 執行歷史 | ~50MB/月 | | 工單記錄 | 6 個月 | 處理歷史 | ~20MB/月 | | AI 對話記錄 | 6 個月 | Copilot 歷史 | ~500MB/月 | | 用戶操作記錄 | 6 個月 | 行為追蹤 | ~200MB/月 | **PostgreSQL 容量評估**: - 每月增量: ~2GB - 6 個月累計: ~12GB - **總計 (含索引): ~20GB** > ✅ **結論**: PostgreSQL 溫資料保留 6 個月,符合 CEO 指示,容量可控。 #### 冷資料歸檔 (Layer 3) | 資料類型 | TTL | 說明 | |---------|-----|------| | 審計日誌 | 永久 | 合規要求,不可刪除 | | 財務記錄 | 7 年 | 法律要求 | | 安全事件 | 3 年 | 資安稽核 | | 系統設定變更 | 1 年 | 變更追蹤 | --- ### 資料清理機制 #### 自動清理 Job ```python # apps/api/app/jobs/data_cleanup.py from datetime import datetime, timedelta from app.database import get_db from app.models import Metric, Alert, Deployment, AIConversation async def cleanup_expired_data(): """每日凌晨 3:00 執行""" six_months_ago = datetime.utcnow() - timedelta(days=180) async with get_db() as db: # 清理過期監控指標 deleted_metrics = await db.execute( delete(Metric).where(Metric.created_at < six_months_ago) ) logger.info(f"Deleted {deleted_metrics.rowcount} expired metrics") # 清理過期告警 (保留 acknowledged 狀態) deleted_alerts = await db.execute( delete(Alert).where( Alert.created_at < six_months_ago, Alert.status != 'archived' # 保留歸檔的告警 ) ) logger.info(f"Deleted {deleted_alerts.rowcount} expired alerts") # ... 其他資料類型 await db.commit() # 更新 Prometheus 指標 cleanup_records_deleted.labels(type="metrics").inc(deleted_metrics.rowcount) cleanup_records_deleted.labels(type="alerts").inc(deleted_alerts.rowcount) ``` #### K8s CronJob ```yaml # k8s/jobs/data-cleanup-cronjob.yaml apiVersion: batch/v1 kind: CronJob metadata: name: awoooi-data-cleanup namespace: awoooi-prod spec: schedule: "0 3 * * *" # 每日凌晨 3:00 jobTemplate: spec: template: spec: containers: - name: cleanup image: awoooi-api:latest command: ["python", "-m", "app.jobs.data_cleanup"] restartPolicy: OnFailure ``` --- ### 資料量監控 #### Prometheus 指標 ```yaml # k8s/monitoring/prometheus/data-alerts.yaml groups: - name: data-storage-alerts rules: # PostgreSQL 容量警告 - alert: PostgreSQLHighUsage expr: | pg_database_size_bytes{datname="awoooi"} > 15 * 1024 * 1024 * 1024 labels: severity: warning annotations: summary: "PostgreSQL 容量已達 15GB" description: "目前使用 {{ $value | humanize1024 }},建議檢查資料清理 Job" # Redis 容量警告 - alert: RedisHighMemory expr: | redis_memory_used_bytes{db="10"} > 1 * 1024 * 1024 * 1024 labels: severity: warning annotations: summary: "Redis DB 10 記憶體使用超過 1GB" ``` --- ### 儲存成本評估 | 層級 | 6 個月容量 | 儲存類型 | 成本 | |------|-----------|---------|------| | Redis (熱) | ~10MB | 內存 | 包含在伺服器 | | PostgreSQL (溫) | ~20GB | SSD | 包含在伺服器 | | 歸檔 (冷) | ~10GB/年 | HDD/S3 | ~$0.5/月 | **結論**: 採用自建伺服器,儲存成本基本為 $0 (已攤提)。 --- ## 影響 ### 正面 - 資料保留策略明確,符合 CEO 6 個月要求 - Redis 維持高效能 (短 TTL) - 歷史資料可追溯 - 儲存成本可控 ### 需要注意 - 清理 Job 需要監控,確保正常執行 - 歸檔資料需要定期備份 - 審計日誌不可刪除,需永久保留 --- ## 變更記錄 | 日期 | 版本 | 變更 | 作者 | |------|------|------|------| | 2026-03-20 | v1.0 | 初版建立 | CTO | --- *此 ADR 記錄資料保留策略的決策過程與實作規範。*