应以 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助手,依托大模型,帮助用户记录、整理和分析音视频内容,体验用大模型做音视频笔记、整理会议记录。
相关推荐
卷无止境8 分钟前
给AI装上一双眼睛:快速构建代码验证器的思路与落地方案大侠归来19 分钟前
常用 MySQL 分库分表方案详解维克兜率天27 分钟前
【维克】指数调整:哪些股票会被“强制买入“?come1123437 分钟前
Codex 下不同场景 模式选择kingx31 小时前
Windows Server 2008 应急加固实战:7 项入侵痕迹排查与修复xiaogai_gai1 小时前
采购业务退款单同步实战:从钉钉审批流到金蝶云星空付款单神也畏惧菠萝1 小时前
Day08 Python流程控制从入门到上瘾:if/match/while/for四件套,从B站登录一路打到猜数字游戏言乐62 小时前
通过 3D 动画直观演示球形瓶内可滑动半圆机构在倾倒时防粘盖、回正时刮膏体的运动学过程quantdash_cc2 小时前
ETF 行情数据清洗实战:字段语义拆解、标的池整理与五个校验清单小熊恋旧2 小时前
Python 面向对象编程:方法、属性、继承与多态详解