用户积分系统怎么设计

用户积分系统怎么设计

  1. 积分总表(User_Point_Wallet)
    作用: 相当于"钱包",只存总额,用于快速读取(展示给用户看)。
java 复制代码
CREATE TABLE user_point_wallet (
    user_id BIGINT PRIMARY KEY,
    total_balance INT DEFAULT 0, -- 当前可用总积分
    version INT DEFAULT 0,       -- 乐观锁版本号
    update_time DATETIME
);
  1. 积分流水表(Point_Flow_Log)
    作用: 相当于"银行流水",记录每一笔增减操作,不可修改,用于对账。
java 复制代码
CREATE TABLE point_flow_log (
    flow_id BIGINT PRIMARY KEY,
    user_id BIGINT,
    amount INT,             -- 变动金额(+100 或 -20)
    type TINYINT,           -- 类型:1-签到,2-购物,3-兑换,4-过期
    ref_id VARCHAR(64),     -- 关联业务单号
    create_time DATETIME
);
  1. 积分明细/分桶表(Point_Detail_Bucket)
    作用: 记录每一笔入账积分的余额和过期时间。
java 复制代码
CREATE TABLE point_detail_bucket (
    id BIGINT PRIMARY KEY,
    user_id BIGINT,
    initial_amount INT,     -- 初始入账金额(如 100)
    current_balance INT,    -- 当前剩余金额(初始 100,消费后变 80)
    expire_time DATETIME,   -- 过期时间(决定了它的生死)
    status TINYINT,         -- 0-有效,1-已用完,2-已过期
    INDEX idx_user_expire (user_id, expire_time) -- 关键索引:按过期时间排序
);

消费时,基于这张表做 FIFO 扣减。

当用户消费 20 分时:

查询 point_detail_bucket,按 expire_time ASC 排序。

找到第一条快过期的记录(1月入账的),current_balance 够扣就扣,不够就扣完这条再找下一条(递归扣减)。

更新 user_point_wallet 总数。 这就是标准的"账本拆分"逻辑。

怎么高效提醒用户积分快过期了?"

错误解法:实时扫描

每天扫数据库 WHERE expire_time = 明天。 死穴: 5 亿用户扫不动。而且如果用户今天把积分花光了,你明天还发短信说"你有积分快过期",用户会觉得你系统有 Bug。

王者解法:离线计算 + 惰性清理

  1. 提醒策略(T+1 离线计算)

针对 5 亿这种体量,别做实时提醒,成本太高且没必要。

方案: 利用大数据平台(Hive/Spark)。

逻辑: 每天凌晨,把 point_detail_bucket 的快照同步到数仓。在数仓里跑一个 SQL,算出"未来 7 天过期的 Bucket 总额 > 0"的用户清单。

触达(MQ 削峰): 拿到清单后,千万别直接调短信接口!5 亿用户哪怕只有 1% 过期,也是 500 万条短信。必须引入 MQ 进行削峰填谷,控制发送速率(如 5000 QPS),避免早高峰把短信网关打挂。

备选方案(轻量级): 如果公司没有大数据基建,可以退回到 '过期日历表' 方案。建一张表按"过期日期"聚合用户 ID,每天扫描。虽然维护成本高一点,但胜在不需要维护 Hadoop 集群,适合中小体量。

  1. 清理策略(惰性 + 定时)

不要每天去 DB 里执行 UPDATE point_detail_bucket SET status = 过期。

读时触发: 用户查积分时,前端根据 expire_time 过滤掉已过期的,展示"有效余额"。

写时触发: 用户消费时,后端过滤掉过期的 Bucket,只扣有效的。

物理归档: 针对长期不活跃的"垃圾数据",后台低频 Job 慢慢搬运到历史冷库。

相关推荐
原来是猿3 小时前
MySQL【内置函数】
数据库·mysql
難釋懷4 小时前
Redis分片集群插槽原理
数据库·redis·缓存
96774 小时前
理解IOC控制反转和spring容器,@Autowired的参数的作用
java·sql·spring
SY_FC4 小时前
实现一个父组件引入了子组件,跳转到其他页面,其他页面返回回来重新加载子组件函数
java·前端·javascript
冷小鱼4 小时前
pgvector 向量数据库完全指南:PostgreSQL 生态的 AI 增强
数据库·人工智能·postgresql
陈天伟教授4 小时前
人工智能应用- 天文学家的助手:08. 星系定位与分类
前端·javascript·数据库·人工智能·机器学习
耀耀_很无聊4 小时前
09_Jenkins安装JDK环境
java·运维·jenkins
yunyun321234 小时前
用Python生成艺术:分形与算法绘图
jvm·数据库·python
ノBye~4 小时前
Centos7.6 Docker安装redis(带密码 + 持久化)
java·redis·docker