前言
继上一篇签到任务之后呢, 就有朋友让我写一下任务积分的领取和使用, 以及回收; 其实前面两种都不难, 就只是积分的加减而已, 真正麻烦的是回收, 有回收的话你就需要考虑到每笔积分存在多种状态的可能了;
结构设计
明细表(mysql)
记录积分的每一笔获取, 消耗的回收的记录, 并且回收会依据里面的过期时间和回收状态来处理;
Id uint `gorm:"column:id;primary_key;auto_increment;" json:"-"`
StreamNumber string `gorm:"column:stream_number;type:varchar(20);COMMENT:'流水号'" json:"streamNumber"`
UserId string `gorm:"column:user_id;type:varchar(20);index;COMMENT:'用户ID'" json:"userId"`
TaskId string `gorm:"column:task_id;type:varchar(50);comment:'任务id'" json:"taskId"`
StreamType int `gorm:"column:stream_type;type:tinyint(1);comment:'明细类型 1获取2消耗3回收'" json:"streamType"`
IntegralNum int64 `gorm:"column:integral_num;type:int(11);default:'0';comment:'积分数量'" json:"integralNum"`
IntegralSource int `gorm:"column:integral_source;type:tinyint(1);comment:'积分来源去向'" json:"integralSource"`
OutTime int64 `gorm:"column:out_time;type:bigint(20);comment:'过期时间';" json:"outTime"`
RecoveryState int `gorm:"column:recovery_state;type:tinyint(1);comment:'回收状态 1已处理2未处理'" json:"recoveryState"`
....相关业务字段
用户任务状态表(mysql)
维护用户的任务状态, 避免任务重复完成, 以及会有多阶段任务的情况
Id uint `gorm:"column:id;primary_key;auto_increment;" json:"id"`
UserId string `gorm:"column:user_id;type:varchar(20);unique_index:idx_user_task;COMMENT:'用户ID'"`
TaskId string `gorm:"column:task_id;type:varchar(50);unique_index:idx_user_task;comment:'任务id'"`
TaskState int `gorm:"column:task_state;type:tinyint(1);comment:'任务状态'"`
....相关业务字段
用户积分key(redis)
积分为了保证性能用redis的hash进行存储, 每个用户一个key, 维护可用积分, 可用相关的流水以及总领取积分数的状态;
IntegralInfo struct {
Available int64 `json:"available"` // 可用
AvailableStream []*IntegralItem `json:"availableStream"` // 可用流水
Total int64 `json:"total"` // 总领取
}
IntegralItem struct {
StreamId uint `json:"streamId"` // 流水Id
TaskId string `json:"taskId"` // 任务Id
Available int64 `json:"available"` // 可用
OutTime int64 `json:"outTime"` // 过期时间
}
领取功能
需求
流程图
消耗功能
需求
流程图
回收功能
需求
流程图
结语
积分功能应该是很多APP都会做的一个功能了, 领取消耗很简单, 但是再加上回收的话就比较复杂了, 何况在不能后置使用的情况下还要保证性能, 这个就值得我们思考如何更有效的实现功能, 那么, 如果在此基础上再加上冻结, 解冻及消耗呢?