目录
一、BitMap
1、概念
2、命令
1.SETBIT
2.GETBIT
3.BITCOUNT
4.BITFIELD
5.BITFIELD RO
6.BITOP
7.BITPOS
二、用户签到
1、思路
2、代码实现
三、当前时间的连续签到天数
1、思路
2、代码实现
一、BitMap
1、概念
Redis中通过String类型实现的一种数据类型,因此存储上限是512M,转换为bit则是2^32个比特位,每一位存储0或1
2、命令
1.SETBIT
向指定key的指定位置中存入0或1
2.GETBIT
获取指定key指定位置的值
3.BITCOUNT
计算指定key中值为1的bit位数量
4.BITFIELD
查询、修改、自增指定key指定位置的值
5.BITFIELD RO
获取指定key中的bit数组,以十进制形式返回
6.BITOP
将多个指定key的结果做位运算
7.BITPOS
查询 bit数组中指定范围内第一个0或1出现的位置
二、用户签到
1、思路
一个月最多有31天,而bitMap有31位,我们可以将当前签到用户的id与当前时间年份+月份作为key,以BitMap为数据结构进行存储用户该月是否签到每一位表示一天,0与1表示是否签到,当用户点击签到请求时,服务器获取当前的时间与当前签到用户的id,以id+当前年月时间作为key,将当前的日作为下标,在BitMap中指定下标位存储1,比如当前签到用户是张三id=1,则key= “sign:1:2020-01”作为key,今天是1月11,则将这个key的第11位的也就是10下标的值修改为1即可表示签到
2、代码实现
void test() {// 1.获取当前用户idLong userId = 1L;// 2.获取当前时间LocalDateTime now = LocalDateTime.now();// 2.1 获取年月String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));// 2.2 获取日int day = now.getDayOfMonth();// 3.存入redis// 3.1 构造keyString key = "sign:" + userId + keySuffix;// 3.2 存入stringRedisTemplate.opsForValue().setBit(key,day - 1,true);}
三、当前时间的连续签到天数
1、思路
当前时间的连续签到天数一定是从现在开始往前数,直到遇到没有签到的那天则结束计算,我们只需要获取到当前用户当前时间对应的bitMap中的每一个比特位,然后从后往前数1当数到0时则停止,最后返回数量即可,我们可以通过BITFIELD RO命令以十进制形式获取到数据,然后按位与1后,如果结果是1则计算变量++后无符合右移1位继续按位与1,直到按位与1等于0时停止。
比如 5 他的二进制是101,从后往前计算他的1的连续个数,101先进行101&1 = 1则计数器+1为1,此时101>>>1 变为10,此时10&1 = 0结束循环计数器值为1,说明从后往前连续的1只有1个
2、代码实现
Integer test() {// 1.获取用户idLong userId = 1L;// 2.获取当前时间LocalDateTime now = LocalDateTime.now();String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));int day = now.getDayOfMonth();// 3.获取对应的签到数值String key = "sign:" + userId + keySuffix;List<Long> result = stringRedisTemplate.opsForValue().bitField(key, BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(day)).valueAt(0));if (result == null || result.isEmpty()) {return null;}// 4.开始计数Long num = result.get(0);if (num == null || num == 0) return null;int count = 0;while (true) {if ((num & 1) == 1) {count++;} else {break;}num >>>= 1;}// 5.返回return count;}