微服务设计之带过期时间的积分系统

前言

积分系统设计通常会为用户的积分设置一个有效期,以此提升用户活跃度。例如,2025年1月2日添加的积分记录将在2026年1月2日自动过期。积分项目在处理带有效期的积分时,通过新增"用户当前可用积分明细表"分离积分明细与可用额度。积分过期时,删除可用积分表中的过期记录,并在用户积分流水表中添加过期记录,更新总额表。消费时,优先使用即将过期的积分,按过期时间排序并累加,不足时拆分记录。此方案有效解决积分过期与使用优先级问题,确保数据准确性和用户体验。

数据模型设计

  1. 需要明确定义用户实体和积分实体的数据结构

  2. **积分过期机制:**设计合理的积分时效计算和状态更新规则

  3. **存储与查询优化:**规划高效的数据存储方案,并优化过期积分的查询性能

  4. **定时任务实现:**开发自动执行积分过期处理的定时调度功能

积分表设计

  • 积分优先扣除最早过期的且小面值的积分

  • 每天需要定时扫码可用积分表,将过期积分删除,并在积分记录表标注好过期记录以及扣减积分详情表记录扣减值

  • 积分总额可直接根据可用积分值计算(即使过期积分没即使删除,也可以通过计算过滤来实现)

我们设计三张表,分布是:用户积分总表 user_point,用户积分流水表 user_point_flow_log,用户当前可用积分明细表 user_point_detail。

user_point 用户积分总表

|---------------|--------|---------------------|
| 字段 | 类型 | 描述 |
| id | BIGINT | 主键 |
| user_id | BIGINT | 用户ID |
| total_balance | INT | 总积分 |
| version | INT | 版本号,Optimistic_Lock |

|----|---------|---------------|---------|
| id | user_id | total_balance | version |
| 1 | 1201 | 20 | 1 |
| 2 | 1202 | 200 | 1 |

user_point_flow_log 用户积分流水表:需要将内容展示给用户,让用户知道自己积分的添加、消耗情况。

字段 类型 描述
id BIGINT 主键,流水号ID
user_id BIGINT 用户ID
type INT 积分记录类型
amount INT 积分
action INT 动作 1: 增加 2:扣减
expire_time DATETIME 过期时间
create_time DATETIME 创建时间
remark Varchar(64) 备注

|----|---------|------|--------|--------|-------------|-------------|--------|
| id | user_id | type | amount | action | expire_time | create_time | remark |
| 1 | 1201 | 1 | 10 | 1 | 2026-12-31 | 2025-12-31 | 签到 |
| 2 | 1201 | 1 | 10 | 1 | 2027-01-01 | 2026-01-01 | 签到 |
| 3 | 1201 | 2 | 10 | 2 | 2026-02-24 | 2026-02-24 | 看剧消耗 |

user_point_detail 当前可用积分明细表 :此表对应的是可用的积分记录,当前积分根据此表值计算得出

字段 类型 描述
id BIGINT 主键ID
user_id BIGINT 用户ID
balance INT 积分
expire_time DATETIME 过期时间
create_time DATETIME 创建时间
deleted TINYINT 删除标记

|-----|---------|---------|-------------|-------------|---------|
| id | user_id | balance | expire_time | create_time | deleted |
| 100 | 1201 | 10 | 2026-12-31 | 2025-12-31 | 1 |
| 101 | 1201 | 10 | 2027-01-01 | 2026-01-01 | 0 |

积分过期时,当前可用积分明细表删除过期记录,用户积分流水表添加一条过期明细,积分总额表更新为当前积分总额。

那么积分过期在什么时候触发呢?可以有以下方案:

  1. 可以每天定时进行一次,对所有的会员操作积分过期计算;
  2. 用户当天首次登录时,进行积分计算,排除过期积分;
  3. 每天定时扫描可用积分表1次,将过期积分删除,并及时更新会员积分总额。

第一种方案需要全部遍历会员表,如果会员表太大,效率低下,而且如果会员并没有过期积分,会做许多无效的统计。第二种方案采用被动触发的形式,虽然也会有无效的积分统计,未能及时清理过期积分,但避免了积分的会员表的全表扫描,性能略高。第三种方案从过期积分入手,主动触发,能及时清理过期积分,只针对过期积分,没有无效的统计,性能优于前两种。

积分使用

积分使用策略如下:

  1. 现在要冻结point个积分
  2. 可用积分表的可用积分记录按过期时间升序排列,依次累加积分额度sumPoint直到sumPoint>=point或记录全部遍历完,用recordIds记录符合要求的积分id,用targetRecord记录最后一条积分记录。
  3. 判断sumPoint与point大小,若:
    1. sumPoint < point,则表明用户积分不足,返回false;
    2. sumPoint = point,则表明当前记录刚好等于消耗记录,进行下一步;
    3. sumPoint > point,则表明最后一条记录大于积分额度,需要将其拆分成两条记录,一条用于抵扣(recordId不变,积分额度为(sumPoint-point)),另一条记录积分剩余(额度为最后一条记录的额度-(sumPoint-point),过期时间为最后一条记录的过期时间)。
  4. 处理可用积分表中的记录、积分明细表记录、积分总额。

积分到期提醒

5亿用户的表,积分到期设计,通过大数据计算积分到期的用户,发送MQ,通过消费MQ发送短信提醒用户。

相关推荐
Mr.朱鹏2 小时前
Linux 服务器 LVM 根分区在线动态扩容
linux·服务器·数据库
摇滚侠2 小时前
《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 数据库初始化机制 阅读笔记 36
数据库·spring boot·笔记
qiuhaipeng12 小时前
Claude code 升级后上下文长度变短问题
java·前端·数据库
wxwx_bscxy3223 小时前
基于Python新冠疫情可视化分析系统的设计与实现
java·数据库·spring boot·python·微信小程序·sqlite
剑之所向4 小时前
.NET 官方`System.Threading.Channels`
前端·javascript·数据库
词却4 小时前
数据库基础:DQL 数据查询语言
数据库·oracle
昌原的儿子LEO6 小时前
Linux IO多路复用与SQLite数据库核心知识点总结
linux·数据库·oracle
山岚的运维笔记6 小时前
mysql 专业笔记 -- 第 8 章:使用变量
运维·数据库·笔记·后端·学习·mysql·dba
聚美智数7 小时前
网安查询-备案查询-网络安全查询API接口介绍
网络·数据库·web安全
坐吃山猪7 小时前
【多线程】Semaphore使用
java·数据库·oracle·多线程