Redis --- 使用BitMap(位图)实现用户签到功能

使用 BitMap 实现用户月签到,可以通过将用户的签到情况映射到一个二进制位图中,进行高效的存储和查询。BitMap 可以节省存储空间,并且提供快速的 bit 操作。以下是使用 BitMap 实现用户月签到的一般思路: 


今日签到实现 


使用setBit()对dayOfMonth-1位置设置成1代表签到:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result sign() {
        Long userId = UserHolder.getUser().getId();
        LocalDateTime now = LocalDateTime.now();
        String keySuffix = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = "sign:" + userId + keySuffix;
        // 获取今天是本月第几天
        int dayOfMonth = now.getDayOfMonth();
        stringRedisTemplate.opsForValue().setBit(key , dayOfMonth - 1, Boolean.TRUE);
        return Result.ok(); 
    }
}

 如何计算连续签到天数?


获取本月到今天为止的所有签到数据:BITFELD key GET u[dayOfMonth] 0 (返回十进制数据)

从后向前遍历每个bit位:与1做与运算,就能得到最后一个bit位。随后右移一位可以使原来的最后一个bit位因超出而抛弃,下一个bit位就成为了最后一个bit位。

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result signCount() {
        Long userId = UserHolder.getUser().getId();
        LocalDateTime now = LocalDateTime.now();
        String keySuffix = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = "sign:" + userId + keySuffix;
        // 获取今天是本月第几天
        int dayOfMonth = now.getDayOfMonth();
        // 获取本月截至到今天位置的所有签到记录,返回的是一个十进制数字
        // BITFIELD sign:5:202502 GET u[?] 0
        List<Long> result = stringRedisTemplate.opsForValue().bitField(
                key, BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
        ); // 返回值是集合是因为可以在bitField()方法内同时做get或者set等多个命令获取多个结果
        if(result == null || result.size() == 0){
            return Result.ok();
        }
        // 获取十进制签到天数结果
        Long num = result.get(0);
        // 使用循环遍历
        int count = 0;
        while(true){
            if((num & 1) == 0){
                break; // 为0未签到,结束
            } else {
                count++; // 不为零则已签到,计数器+1
            }
            // 把数字右移一位,抛弃最后一个bit位,继续下一个bit位
            num >>>= 1;
        }
        return Result.ok(count);
    }
}

通过 Redis 的 BitMap 操作,可以非常高效地存储和查询用户的签到信息。常用的 Redis 命令如 SETBITGETBITBITCOUNT 可以帮助我们方便地操作用户的签到状态。BitMap 适用于大量数据的高效存储与查询,特别适合这种 "签到" 等具有固定天数、每位表示一天的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

记得开心一点嘛

您的打赏是对我最大的鼓励与期待

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值