数据库存储签到信息存在的问题:
数据库应有的字段:userId year month day
当用户签到完成后向数据库插入一条数据,如果用户量非常大数据库数据量会非常大,一个用户如果每天都签到得有365条数据
使用redis实现签到
redis 中有一个bitmap的数据结构(本质上还是String),可以对每个bit位进行操作,我们可以使用 1 代表签到,0 代表未签
SETBIT key offset value
offset:bit索引 从0开始
value:1 或者 0
GETBIT key offset
java代码
LocalDateTime now = LocalDateTime.now();
String suffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
int dayOfMonth = now.getDayOfMonth();
String key = "sign" + userId + suffix;
stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
最终呈现的效果,对于每个用户而言,每个月为一个key,签到信息就可以很好的展示了,并且内存消耗非常小,一个用户一年也只有12条数据
sign:10086:202304 00101010101010....
sign:10086:202305 10101010101010...
统计每个月的签到次数
BITCOUNT key [start end [BYTE | BIT]]
BITCOUNT key 0 10 BYTE 统计第1个字节到第11个字节中 bit 为 1的个数
BITCOUNT key 0 10 BIT 统计第1个bit到第11个bit中bit为1的个数
java代码,由于一个月最多有31天所以我们统计 0 - 30 即可
Long count = stringRedisTemplate.execute(connection -> connection.bitCount(key.getBytes(), 0, 30), true);