一、积分签到系统分析
1、背景
目前,在各大软件中,都应用到了积分签到系统,用户可以通过签到、评论、观看视频积攒积分,在后续还可以通过积分数量去参加排行榜、兑换礼品优惠券等,可以提高用户的积极性与活跃度。
接下来我们以一个学习系统为例,来说一说积分签到系统是如何实现的。
2、积分规则
用户在学习系统的各种交互行为都可以产生积分,积分值与行为类型有关,不同类型的操作获得不等的分数。
(1)签到规则
-
签到1天给1分
-
连续7天额外奖励10分
-
连续14天额外奖励20分
-
连续28天额外奖励40分
每月签到进度在当月第一天重置
(2)学习规则
-
每学习一小节积分+10,每天获得上限50分
(3)交互规则
有效交互数据参与积分规则,无效数据会被删除
-
写评论,积分+10 每日获得上限为50分
-
写问答,积分+5 每日获得上限为20分
-
写笔记,积分+3,每次被采集+2 每日获得上限为20分
3、数据表设计
(1)签到表
签到表包含的最核心的两个要素:
-
谁签到:用户id
-
什么时候签的:签到日期
还可以添加一些其他的功能要素:
-
补签功能:要有补签标示
-
按照年、月统计的功能:签到日期可以按照年、月、日分离保存
(2)Bitmap结构
通过观察签到表的设计,我们会发现一条签到记录就会占用22个字节,而我们每天的签到记录有很多,这样会很浪费空间,为了节省存储空间,我们可以使用Bitmap结构来保存某个用户一月份的打卡记录。
每一个bit对应当月的每一天,形成映射关系,用0和1分别标识是否打卡,这种思路称为bitmap(位图)。
在Redis中,bitmap底层还是基于String类型实现的,存储数据是以二进制(bit位)为单位进行存储的,bitmap在处理大量数据统计和判断时,可以只占用非常小的一部分内存,并且计算速度非常高效!
下面是Redis中bitmap的操作命令:
(3)积分表
需要设计如下字段:
-
本次得到积分值
-
积分方式
-
获取积分时间
-
获取积分的人
二、查询签到
在签到日历中,需要把当前登录用户本月第一天到今天为止的所有签到过的日期高亮显示。
我们需要把签到记录返回给前端,具体来说就是每一天是否签到的数据。
在前端,0和1代表false和true,也就是签到或没签到。
因此,我们最终返回的结果是一个0或1组成的数组,对应从本月第1天到今天为止每一天的签到情况。
三、新增签到
1、需求分析
在个人中心的积分页面,用户每天都可以签到一次,而在后台,要做的事情就是把BitMap中的与签到日期对应的bit位设置为1。
另外,为了便于统计,我们计划每个月为每个用户生成一个独立的KEY,因此KEY中必须包含用户信息、月份信息。
设计如下:
-
sign:id:xxx:202301 #sign:uid:用户id:年月
2、问题分析
四、新增积分
1、需求介绍
用户签到、学习、参与互动问答、提交学习笔记等行为都可以产生积分,并基于积分形成排行榜。积分当月有效,月底清零。
由积分规则可知,获取积分的行为多种多样,而且每一种行为都有自己的独立业务。而这些行为产生的时候需要保存一条积分明细到数据库。
我们显然不能要求其它业务的开发者在开发时帮我们新增一条积分记录,这样会导致原有业务与积分业务耦合。
因此必须采用异步方式,将原有业务与积分业务解耦。如果有必要,甚至可以将积分业务抽离,作为独立微服务。
2、思路分析
要实现服务之间的解耦,可以使用MQ,实现流程如下:
3、发送消息
接下来,我们就可以改造之前的业务,在所有可以获取积分的业务中发送MQ消息了。
包括下列地方:
-
签到
-
完成一小节的学习(视频、考试均可)
-
提问回答
-
写笔记
-
笔记被采集
4、逻辑分析
(1)首先判断是否有积分上限,如果没有,直接保存积分记录
(2)如果有积分上限,先查询今日已获得积分,并判断是否超过每日上限
(3)如果未超过,则保存积分记录,如果超过,直接结束
五、查询积分
在个人中心,用户可以查看当天各种不同类型的已获得的积分和积分上限:
可以看到,页面需要的数据:
-
积分类型描述
-
今日已获取积分值
-
积分上限
根据需求,从数据库中查出对应的数据返回给前端即可。