基本规则
- 每天第一次访问网站资源,积分
+1
- 若有一天未访问网站资源,则积分
-1
其它要求
- 积分会显示在用户头像上,因此像评论列表这种,一个页面可能出现上百个头像的位置也要获取对应用户的
当前积分
,也完全可能有重复的用户
我和后端讨论了几个方案:
方案1:
方案逻辑:
记录用户近几次访问的情况,当需要获取积分时根据这几次访问的时间临时计算分数。
方案问题:
因为只记录最近几次(假设3次)的访问情况,若出现用户先积了2分(11
),然后隔一天访问一次(110101
),按照最近3次有效访问计算,这个用户是1
分,但实际应该是2
分。若是增加记录的天数,那相应的也可能出现11010101010101010...
更长的情况出现。逼到极限就是从功能上线的那一天开始计算,所以不太合适。
方案2:
- 新增
当前分数
参数 - 新增
上一次分数计算时间
参数 - 已有
用户操作记录
表
方案逻辑:
- 当用户访问网站资源时,生成一条操作记录。若此记录为当天的第一个
访问资源
记录时,当前积分+1
,并更新上一次分数计算时间
- 当用户积分被查看时(不论是用户自己还是其他用户),若
上一次分数计算时间与昨晚23:59间隔小于一天
,则直接返回当前分数 - 当用户积分被查看时(不论是用户自己还是其他用户),若
上一次分数计算时间与昨晚23:59间隔大于一天
,则将当前积分
减去间隔的完整天数
,并返回分数,并更新上一次分数计算时间
方案问题:
虽然积分逻辑没有问题,但不适用于显示在列表头像上,因为这样会导致有多少头像就进行多少次计算,重复的头像也会单独判断,导致性能下降。
方案3:
方案逻辑:
- 每天第一次访问资源,积分
+1
- 每天晚上跑个脚本,为所有用户计算今天是否应该减分
方案问题:
开发认为这个方案非常丑陋
,但在产品眼里“不就是每天跑个脚本”
嘛
其它说明
开发基本没有话语权,以需求为主导。
碰到性能与需求相冲突时,基本都是先不考虑性能
。
但有没有一个能让开发也能接受的方案?
我认为你提出的方案 2 已经很接近最终的答案了,我在你的方案 2 上提出一些改进。
首先我把环境限定在数据库。
改进方案
用户积分
、用户注册日期
、更新日期
。根据你的方案2,我默认你有办法判断用户是否是今天第一次访问了。
那么这张表为什么只需要三个字段呢?这是关键点:
如果用户需要加积分了,那么
用户积分
需要加一,用户注册日期
增加一天,更新日期
修改为今天也不一定是
用户注册日期
,我只是举个例子,根据需求来确定,可以是用户第一次访问资源的日期
计算方式
使用下面的公式,含义是
用户积分
减去你落后的分数。如果你每天都访问了,
用户注册日期
会增加访问的天数,应该都为 0 才对。那么分数就能对的上了。使用
if(更新日期=今天, 0 , 1)
的原因是会多扣分,所以用更新日期判断一下,是否需要补这一分。用户积分 - daydiff(当前时间, 用户注册时间) + if(更新日期=今天, 0 , 1)
举例子
在应用环境中,
today
变量换为curdate()
性能
这种方案的性能是可以保障的,除非你的用户积分查询一次能够达到十几万,否则对于数据库来说都是非常轻松的。
并且只要你能够保证源头上限定每天更新一次正常,那么写入的效率也是非常高的,一条 sql 就能够同时更新积分和时间两个字段,根本不用查询。
最后
如果对这种方式有什么疑问或者补充需求,可以联系我。
更新
重新理解了一下你的需求,发现是按天处理,不需要考虑小时,这样简单很多。