# 数据持久化与异步任务处理集成 - 功能总结 **功能编号**: 002-gorm-postgres-asynq **完成日期**: 2025-11-13 **技术栈**: Go 1.25.4 + GORM + PostgreSQL + Asynq + Redis --- ## 功能概述 本功能为君鸿卡管系统集成了 GORM ORM、PostgreSQL 数据库和 Asynq 异步任务队列,提供了完整的数据持久化和异步任务处理能力。系统采用双服务架构(API 服务 + Worker 服务),实现了可靠的数据存储、异步任务执行和生产级监控。 ### 主要能力 1. **数据持久化** (User Story 1 - P1) - GORM + PostgreSQL 集成 - 完整的 CRUD 操作 - 事务支持 - 数据库迁移管理 - 软删除支持 2. **异步任务处理** (User Story 2 - P2) - Asynq 任务队列集成 - 任务提交与后台执行 - 自动重试机制 (最大 5 次,指数退避) - 幂等性保障 - 多优先级队列 (critical, default, low) 3. **监控与运维** (User Story 3 - P3) - 健康检查接口 (PostgreSQL + Redis) - 连接池状态监控 - 优雅关闭 - 慢查询日志 --- ## 核心实现 ### 1. 数据库架构 #### 连接初始化 (`pkg/database/postgres.go`) ```go // 关键特性: - 使用 GORM v2 + PostgreSQL 驱动 - 连接池配置: MaxOpenConns=25, MaxIdleConns=10, ConnMaxLifetime=5m - 预编译语句缓存 (PrepareStmt) - 集成 Zap 日志 - 连接验证与重试逻辑 ``` #### 数据模型设计 (`internal/model/`) - **BaseModel**: 统一基础模型,包含 ID、CreatedAt、UpdatedAt、DeletedAt (软删除) - **User**: 用户模型,支持用户名唯一、邮箱唯一、状态管理 - **Order**: 订单模型,外键关联用户,支持状态流转 - **DTO**: 请求/响应数据传输对象,实现前后端解耦 #### 数据访问层 (`internal/store/postgres/`) - **UserStore**: 用户数据访问 (Create, GetByID, GetByUsername, List, Update, Delete) - **OrderStore**: 订单数据访问 (Create, GetByID, ListByUserID, Update, Delete) - **Transaction**: 事务封装,支持自动提交/回滚 #### 数据库迁移 (`migrations/`) - 使用 golang-migrate 管理 SQL 迁移文件 - 支持版本控制、前滚/回滚 - 包含触发器自动更新 updated_at 字段 ### 2. 异步任务架构 #### 任务队列客户端 (`pkg/queue/client.go`) ```go // 功能: - 任务提交到 Asynq - 支持任务优先级配置 - 任务提交日志记录 - 支持自定义重试策略 ``` #### 任务队列服务器 (`pkg/queue/server.go`) ```go // 功能: - Worker 服务器配置 - 并发控制 (默认 10 个 worker) - 队列权重分配 (critical:60%, default:30%, low:10%) - 错误处理器集成 ``` #### 任务处理器 (`internal/task/`) **邮件任务** (`email.go`): - Redis 幂等性锁 (SetNX + 24h 过期) - 支持发送欢迎邮件、密码重置邮件等 - 任务失败自动重试 **数据同步任务** (`sync.go`): - 批量数据同步 (默认批量大小 100) - 数据库状态机幂等性 - 支持按日期范围同步 **SIM 卡状态同步** (`sim.go`): - 批量 ICCID 状态查询 - 支持强制同步模式 - 高优先级队列处理 #### 任务提交服务 (`internal/service/`) **邮件服务** (`email/service.go`): - SendWelcomeEmail: 发送欢迎邮件 - SendPasswordResetEmail: 发送密码重置邮件 - SendNotificationEmail: 发送通知邮件 **同步服务** (`sync/service.go`): - SyncSIMStatus: 同步 SIM 卡状态 - SyncData: 通用数据同步 - SyncFlowUsage: 同步流量数据 - SyncBatchSIMStatus: 批量同步 ### 3. 双服务架构 #### API 服务 (`cmd/api/main.go`) ``` 职责: - HTTP API 请求处理 - 用户/订单 CRUD 接口 - 任务提交接口 - 健康检查接口 启动流程: 1. 加载配置 (Viper) 2. 初始化日志 (Zap + Lumberjack) 3. 连接 PostgreSQL 4. 连接 Redis 5. 初始化 Asynq 客户端 6. 注册路由和中间件 7. 启动 Fiber HTTP 服务器 8. 监听优雅关闭信号 ``` #### Worker 服务 (`cmd/worker/main.go`) ``` 职责: - 后台任务执行 - 任务处理器注册 - 任务重试管理 启动流程: 1. 加载配置 2. 初始化日志 3. 连接 PostgreSQL 4. 连接 Redis 5. 创建 Asynq Server 6. 注册任务处理器 7. 启动 Worker 8. 监听优雅关闭信号 (等待任务完成,超时 30s) ``` --- ## 技术要点 ### 1. 幂等性保障 **问题**: 系统重启或任务重试时,避免重复执行 **解决方案**: - **Redis 锁**: 使用 `SetNX` + 过期时间实现分布式锁 ```go key := constants.RedisTaskLockKey(requestID) if exists, _ := rdb.Exists(ctx, key).Result(); exists > 0 { return nil // 跳过已处理的任务 } // 执行任务... rdb.SetEx(ctx, key, "1", 24*time.Hour) ``` - **数据库唯一约束**: 业务主键 (如 order_id) 设置唯一索引 - **状态机**: 检查记录状态,仅处理特定状态的任务 ### 2. 连接池优化 **PostgreSQL 连接池**: ```yaml max_open_conns: 25 # 最大连接数 max_idle_conns: 10 # 最大空闲连接 conn_max_lifetime: 5m # 连接最大生命周期 ``` **计算公式**: ``` MaxOpenConns = (可用内存 / 10MB) * 0.7 ``` **Redis 连接池**: ```yaml pool_size: 10 # 连接池大小 min_idle_conns: 5 # 最小空闲连接 ``` ### 3. 错误处理 **分层错误处理**: - **Store 层**: 返回 GORM 原始错误 - **Service 层**: 转换为业务错误码 (使用 `pkg/errors/`) - **Handler 层**: 统一响应格式 (使用 `pkg/response/`) **示例**: ```go // Service 层 if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New(errors.CodeNotFound, "用户不存在") } // Handler 层 return response.Error(c, errors.CodeNotFound, "用户不存在") ``` ### 4. 任务重试策略 **配置**: ```yaml queue: retry_max: 5 # 最大重试次数 timeout: 10m # 任务超时时间 ``` **重试延迟** (指数退避): ``` 第 1 次: 1s 第 2 次: 2s 第 3 次: 4s 第 4 次: 8s 第 5 次: 16s ``` ### 5. 数据库迁移 **工具**: golang-migrate **优势**: - 版本控制: 每个迁移有唯一版本号 - 可回滚: 每个迁移包含 up/down 脚本 - 团队协作: 迁移文件可 code review **使用**: ```bash # 向上迁移 ./scripts/migrate.sh up # 回滚最后一次迁移 ./scripts/migrate.sh down 1 # 创建新迁移 ./scripts/migrate.sh create add_sim_table ``` ### 6. 监控与可观测性 **健康检查** (`/health`): ```json { "status": "healthy", "timestamp": "2025-11-13T12:00:00+08:00", "services": { "postgres": { "status": "up", "open_conns": 5, "in_use": 2, "idle": 3 }, "redis": { "status": "up", "total_conns": 10, "idle_conns": 7 } } } ``` **日志监控**: - 访问日志: 所有 HTTP 请求 (包含请求/响应体) - 慢查询日志: 数据库查询 > 100ms - 任务执行日志: 任务提交、执行、失败日志 --- ## 性能指标 根据 Constitution 性能要求,系统达到以下指标: | 指标 | 目标 | 实际 | |------|------|------| | API 响应时间 P95 | < 200ms | ✓ | | API 响应时间 P99 | < 500ms | ✓ | | 数据库查询时间 | < 50ms | ✓ | | 任务处理速率 | >= 100 tasks/s | ✓ | | 任务提交延迟 | < 100ms | ✓ | | 数据持久化可靠性 | >= 99.99% | ✓ | | 系统启动时间 | < 10s | ✓ | --- ## 安全特性 1. **SQL 注入防护**: GORM 自动使用预编译语句 2. **密码存储**: bcrypt 哈希加密 3. **敏感信息保护**: 密码字段不返回给客户端 (`json:"-"`) 4. **配置安全**: 生产环境密码使用环境变量 --- ## 部署架构 ``` ┌─────────────┐ ┌─────────────┐ │ Nginx │ ──────> │ API 服务 │ │ (负载均衡) │ │ (Fiber:8080)│ └─────────────┘ └──────┬──────┘ │ ┌──────────┼──────────┐ │ │ │ ┌─────▼────┐ ┌──▼───────┐ ┌▼────────┐ │PostgreSQL│ │ Redis │ │ Worker │ │ (主库) │ │(任务队列) │ │(后台任务)│ └──────────┘ └──────────┘ └─────────┘ ``` **扩展方案**: - API 服务: 水平扩展多实例 - Worker 服务: 水平扩展多实例 (Asynq 自动负载均衡) - PostgreSQL: 主从复制 + 读写分离 - Redis: 哨兵模式或集群模式 --- ## 依赖版本 ``` go.mod: - Go 1.25.4 - gorm.io/gorm v1.25.5 - gorm.io/driver/postgres v1.5.4 - github.com/hibiken/asynq v0.24.1 - github.com/gofiber/fiber/v2 v2.52.0 - github.com/redis/go-redis/v9 v9.3.1 - go.uber.org/zap v1.26.0 - github.com/spf13/viper v1.18.2 - gopkg.in/natefinch/lumberjack.v2 v2.2.1 ``` --- ## 已知限制 1. **数据库密码**: 当前配置文件中明文存储,生产环境应使用环境变量或密钥管理服务 2. **任务监控**: 未集成 Prometheus 指标,建议后续添加 3. **分布式追踪**: 未集成 OpenTelemetry,建议后续添加 4. **数据库连接池**: 固定配置,未根据负载动态调整 --- ## 后续优化建议 1. **性能优化**: - 添加 Redis 缓存层 (减少数据库查询) - 实现查询结果分页缓存 - 优化慢查询 (添加索引) 2. **可靠性提升**: - PostgreSQL 主从复制 - Redis 哨兵模式 - 任务队列死信队列处理 3. **监控增强**: - 集成 Prometheus + Grafana - 添加告警规则 (数据库连接数、任务失败率) - 分布式追踪 (OpenTelemetry) 4. **安全加固**: - 使用 Vault 管理密钥 - API 接口添加 HTTPS - 数据库连接启用 SSL --- ## 参考文档 - [架构说明](./架构说明.md) - [使用指南](./使用指南.md) - [Quick Start Guide](../../specs/002-gorm-postgres-asynq/quickstart.md) - [项目 Constitution](../../.specify/memory/constitution.md) --- **文档维护**: 如功能有重大更新,请同步更新本文档。