MongoDB中用户积分明细如何建表_流水账与总额同步写入

张开发
2026/4/9 22:42:07 15 分钟阅读

分享文章

MongoDB中用户积分明细如何建表_流水账与总额同步写入
应以 user_id 为分片键并建 {user_id: 1, timestamp: -1} 复合索引流水需含 type/ref_id/reason 字段总额与流水须同事务更新Redis 仅作短 TTL 二级缓存批量操作用 bulkWrite 或 $merge所有补偿脚本须幂等。用 user_id 作为分片键别用 timestamp积分明细本质是高频写、范围查比如查某用户最近 30 条、低频全量聚合的场景。如果按时间分片新写入全打到同一个 chunk容易热点而 user_id 天然分散写入压力查单个用户也快。常见错误是建索引时只加 { timestamp: -1 }结果 find({ user_id: u123 }) 走不了索引——必须复合索引{ user_id: 1, timestamp: -1 } 才能高效支持「某用户按时间倒序查流水」。分片集群下sh.shardCollection(db.points_log, { user_id: hashed }) 比 { timestamp: 1 } 更稳单机或副本集也建议用 user_id 做查询主路径避免后期迁移成本别在 timestamp 上单独建 TTL 索引清理旧数据——TTL 删除会锁文档影响写入改用后台定时 job 按 user_id timestamp 分批删points_log 表里存操作类型和原始依据别只记净变化只存 delta: 100 看似省事但运营对账、用户申诉时完全没法追溯是签到还是订单返利还是客服补发所以每条流水必须含 type如 sign_in、order_refund、ref_id关联订单号/活动 ID、reason可选描述。典型错误是把「总额更新」和「流水写入」拆成两个独立事务导致中间状态不一致——比如扣积分成功但流水写失败用户发现余额不对却无迹可查。type 字段用枚举字符串别用数字编码可读性差、易错配ref_id 必须有且长度可控如订单号截取前 16 位哈希避免超长影响索引效率写流水和更新用户总额必须在同一个 session 中用 withTransaction 包裹MongoDB 4.0 支持多文档事务用户总额不要实时计算但也不能全靠应用层缓存每次查余额都 db.points_log.aggregate(...) 求和QPS 上百就扛不住。全放 Redis 缓存宕机或并发更新时容易和 DB 不一致。折中方案是总额字段存在 users 集合里由数据库事务保证和流水强一致Redis 只做二级缓存带 short TTL比如 5 分钟 主动失效写流水后删 Redis key。 通义听悟 阿里云通义听悟是聚焦音视频内容的工作学习AI助手依托大模型帮助用户记录、整理和分析音视频内容体验用大模型做音视频笔记、整理会议记录。

更多文章