Skip to content

Latest commit

 

History

History
114 lines (86 loc) · 4.74 KB

File metadata and controls

114 lines (86 loc) · 4.74 KB

ADR-004: 数据库选型 -- PostgreSQL + Redis + TimescaleDB

上下文

TokenRouter 的数据存储需求涵盖多个维度:

数据类型 特征 操作模式
用户/API Key 结构化、关系型、强一致性 CRUD、事务
请求日志 高频写入、按时间范围查询 INSERT、聚合查询
缓存数据 高频读写、短生命周期、可丢失 GET/SET、TTL过期
用量统计 时序数据、按时间聚合 时间范围查询、降采样
模型定价 低频变更、全局共享 全量读取、偶尔更新

候选方案:

方案 组合 优势 劣势
A PostgreSQL + Redis + TimescaleDB 关系型+缓存+时序各司其职 运维三套系统
B MongoDB + Redis 文档模型灵活、减少组件数 时序查询能力弱、事务支持不如PG
C 纯Redis(Redis Stack) 极致性能、组件最少 数据持久化风险、复杂查询能力弱、内存成本高

决策

选择 方案A:PostgreSQL + Redis + TimescaleDB

PostgreSQL -- 关系型数据主库

负责存储用户、API Key、模型定价等结构化数据,以及请求日志。

选型理由:

  • ACID事务:用户注册、API Key创建、计费记录等操作需要强事务保证
  • JSON支持JSONB类型可存储请求/响应的原始JSON,便于调试和审计
  • 成熟生态:Go的GORM对PostgreSQL支持最完善,迁移工具丰富
  • TimescaleDB兼容:TimescaleDB是PostgreSQL扩展,共享同一数据库实例,无需额外运维
// GORM模型定义示例
type User struct {
    ID          uuid.UUID      `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"`
    Email       string         `gorm:"uniqueIndex;not null"`
    Name        string         `gorm:"not null"`
    Plan        string         `gorm:"default:'free'"`
    QuotaLimit  int64          `gorm:"default:1000000"`
    CreatedAt   time.Time
    UpdatedAt   time.Time
}

Redis -- 缓存与实时数据

负责缓存(KV Cache元数据)、限流计数、会话状态、供应商健康检查。

选型理由:

  • 亚毫秒延迟:缓存查询延迟 < 1ms,满足P99 < 100ms的总体延迟目标
  • 丰富数据结构:String、Hash、Set、Sorted Set覆盖所有缓存场景
  • TTL机制:原生支持Key过期,无需手动清理
  • Pub/Sub:可用于缓存失效通知和配置变更广播

TimescaleDB -- 时序数据

基于PostgreSQL的时序数据库扩展,用于存储用量统计(daily_usage表)和缓存命中率趋势。

选型理由:

  • 零额外运维:作为PostgreSQL扩展安装,共享同一实例,不增加运维负担
  • 自动分区create_hypertable()自动按时间分区,查询时自动裁剪无关分区
  • 连续聚合create_continuous_aggregate()自动预计算小时/天/周粒度的聚合数据
  • SQL兼容:完全兼容PostgreSQL SQL语法,可使用GORM直接查询
-- TimescaleDB连续聚合:每小时自动预计算
CREATE MATERIALIZED VIEW hourly_usage
WITH (timescaledb.continuous) AS
SELECT
    time_bucket('1 hour', time) AS bucket,
    user_id,
    model,
    SUM(prompt_tokens) AS prompt_tokens,
    SUM(completion_tokens) AS completion_tokens,
    SUM(cost_usd) AS cost_usd,
    COUNT(*) AS request_count
FROM daily_usage
GROUP BY bucket, user_id, model;

-- 自动刷新策略
SELECT add_continuous_aggregate_policy('hourly_usage',
    start_offset => INTERVAL '3 hours',
    end_offset => INTERVAL '1 hour',
    schedule_interval => INTERVAL '1 hour');

后果

正面影响

  • 需求全覆盖:关系型数据(PG)+ 缓存(Redis)+ 时序(TimescaleDB)的组合精确覆盖所有数据场景,无短板
  • 运维成本低:TimescaleDB作为PG扩展,实际只需运维PostgreSQL和Redis两套系统
  • 事务一致性:PostgreSQL的ACID保证确保计费和配额操作的准确性
  • 查询能力强:SQL的JOIN、窗口函数、CTE等能力支持复杂的统计分析需求
  • 扩展路径清晰:数据量增长后,PostgreSQL可迁移至Citus分布式方案,Redis可迁移至Cluster模式

负面影响

  • 运维复杂度:需要维护PostgreSQL和Redis两套系统(含备份、监控、故障恢复)
  • 连接管理:Go服务需要同时维护PG连接池和Redis连接池,需合理配置以避免资源耗尽
  • 缓存一致性:Redis缓存与PostgreSQL主数据之间的一致性需要应用层保证(Cache-Aside模式)
  • TimescaleDB学习成本:团队需要学习TimescaleDB特有的概念(hypertable、continuous aggregate、retention policy)