黑马点评开发日记-用户签到

签到功能

我们可以采用类似这样的方案来实现我们的签到需求。

我们按月来统计用户签到信息,签到记录为1,未签到则记录为0.

把每一个bit位对应当月的每一天,形成了映射关系。用0和1标示业务状态,这种思路就称为位图(BitMap)。这样我们就用极小的空间,来实现了大量数据的表示

Redis中是利用string类型数据结构实现BitMap,因此最大上限是512M,转换为bit则是 2^32个bit位。
BitMap的操作命令有:

  • SETBIT:向指定位置(offset)存入一个0或1
  • GETBIT :获取指定位置(offset)的bit值
  • BITCOUNT :统计BitMap中值为1的bit位的数量
  • BITFIELD :操作(查询、修改、自增)BitMap中bit数组中的指定位置(offset)的值
  • BITFIELD_RO :获取BitMap中bit数组,并以十进制形式返回
  • BITOP :将多个BitMap的结果做位运算(与 、或、异或)
  • BITPOS :查找bit数组中指定范围内第一个0或1出现的位置
@Override
    public Result sign() {

        //1.获取当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2。获取日期
        LocalDateTime now = LocalDateTime.now();
        //3.拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMMMM"));
        String key=USER_SIGN_KEY+userId+keySuffix;
        //4.获取今天是本月第几天
        int dayOfMonth = now.getDayOfMonth();
        //5.写入redis
        stringRedisTemplate.opsForValue().setBit(key,dayOfMonth-1,true);

        return Result.ok();
    }

签到统计

在这里插入图片描述
我们可以先获取本月到目前为止的所有签到记录,返回一个十进制数字。我们可以让它与1做与运算,得到该数字的最后一位。判断最后一位是否为0,为0则终止,为1则计数器+1,继续便利。

@Override
    public Result signCount() {

        //1.获取当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2。获取日期
        LocalDateTime now = LocalDateTime.now();
        //3.拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMMMM"));
        String key=USER_SIGN_KEY+userId+keySuffix;
        //4.获取今天是本月第几天
        int dayOfMonth = now.getDayOfMonth();
        //5.获取本月到今天为止所有的签到记录,返回的是一个十进制数字
        List<Long> result = stringRedisTemplate.opsForValue()
                .bitField(key, BitFieldSubCommands.create().
                        get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).
                        valueAt(0));

        if (result==null||result.isEmpty()){
            return Result.ok(0);
        }
        //6.循环遍历
        int count=0;
        Long num = result.get(0);
        //7.让这个数字与1做与运算,得到数字最后一个bit位
        while (true){
            //判断这个bit位是否为0
            if ((num & 1)==0) {
               //如果为0,未签到,结束
                break;
            }else {
                //如果不为0,说明已经签到,计数器+1
                count++;
            }
            //把数字右移一位,抛弃最后一个bit位,继续下一个bit位
            num>>>=1;
        }

        return Result.ok(count);

    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值