瑞士军刀
Redis
2020年11月28日
签到
需求分析
Redis应用之用户签到
![f3291c2d2e0a40fa6264df1322a0ca01.png](https://img-blog.csdnimg.cn/img_convert/f3291c2d2e0a40fa6264df1322a0ca01.png)
在很多的互联网应用中,我们基本都存在签到送积分、签到领取奖励这样的需求,比如:
1、签到累计送积分
2、签到中断,重置计数,每月初重置计数
3、显示用户某个月的签到次数
4、在日历控件上展示用户每月签到的情况,可以切换年月显示
1.
MySQL实现方案
【】数据库表设计
在数据库保存用户的签到数据,每次签到均生成一条记录保存,对于用户量比较大的应用,数据库可能就会扛不住,比如一千万签到狂魔用户一个月会有三亿条数据,这是非常庞大的,并且,针对上面的需求分析,MySQL在判断用户某个月签到,和月份的切换上,需要写很多相对复杂的SQL语句,如果涉及到积分,甚至还会发生多表联查,这对于数据库来说压力会非常的大
2.
BitMap的实现方案
BitMaps位图,它是Redis中基于String类型的按位操作,高阶数据类型的一种,BitMap最大支持232位,512m的内存可以储存42.9亿的字节信息。
位图中,他是由一组bit组成的,每个bit位对应0和1两个状态,虽然内部还是采用String类型存储,但Redis提供了一些指令可以直接操作位图,可以把位图看做一个二进制的bit数组,数组的下标就是偏移量。
常见指令:
![f709d69d6436f53c8d3802eeb48e1c09.png](https://img-blog.csdnimg.cn/img_convert/f709d69d6436f53c8d3802eeb48e1c09.png)
我们的业务需求需要按月存储签到次数,最简单的方式是按每用户每月存一条签到数据,Key的格式为user:sign:userid:yyyyMM,位图的每一位代表一天的签到,例如:user:sign:98:202011表示用户98在2020年11月的签到情况。那么:
【这里放图】
3.
代码实现
用户签到Service
/** * 用户签到 * * @param accessToken 登录用户 token * @param dateStr 查询的日期,默认当天 yyyy-MM-dd * @return 连续签到次数 */public int doSign(String accessToken, String dateStr) {
// 获取登录用户信息 SignInDinerInfo signInDinerInfo = loadSignInDinerInfo(accessToken); // 获取日期 Date date = getDate(dateStr); //