Redis使用BitMap结构实现简单用户签到

本文通过对比MySQL和Redis在用户签到功能中的应用,探讨了使用Redis的BitMap结构进行空间优化的策略。通过位运算,将每月签到信息存储在一个BitMap中,大大减少了存储需求。详细介绍了如何利用Redis的SETBIT、GETBIT、BITCOUNT等命令实现签到功能,并给出了具体的Java代码实现。这种方法在用户量较大时,能有效节省存储资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

redis引入场景:

       或许有人会说,我只需要使用mysql数据库就能完成用户签到记录的功能了呀,为什么还要使用 redis呢?
       用户签到一次,对应到mysql数据库中就是一条记录。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/821073e32b7840b2b3f73766f7c01952.png)        这里我们有6个字段,bigint的id、bigint的user_id、year类型的year、tiny类型的month、date类型的date、tinyint类型的is_backup。对应的字节数(8 + 8 + 1 + 1 + 3 + 1)=22字节,也就是用户签到一次就需要22字节来进行存储。我们假设一天只签到一次,按照30天来进行计算,22*30=660。也就是一个人每天签到一次,一个月需要660字节来进行存储,那当我们的用户量达到百万甚至千万,一年下来,需要的空间并不是我们可以接收的。

redis中的BitMap结构

我们按月来统计用户签到信息,签到记录为1,未签到则记录为0。把每一个bit位对应当月的每一天,形成了映射关系。用0和1标示业务状态,这种思路就称为位图(BitMap)。这样我们就用极小的空间,来实现了大量数据的表示。即便每天签到,一个月最多31位,也就是最多4个字节,与660字节相比,有百倍的容量差距。

BitMap的知识大致了解

  1. SETBIT:向指定位置(offset)存入一个0或1
  2. GETBIT :获取指定位置(offset)的bit值
  3. BITCOUNT :统计BitMap中值为1的bit位的数量
  4. BITFIELD :操作(查询、修改、自增)BitMap中bit数组中的指定位置(offset)的值
实现思路

我们可以把年和月作为bitMap的key,然后保存到一个bitMap中,每次签到就到对应的位上把数字从0变成1,只要对应是1,就表明说明这一天已经签到了,反之则没有签到。
注意:因为BitMap底层是基于String数据结构(这里的String是redis中的String),因此其操作也都封装在字符串相关的操作中了。

1. 定义接口

    /**
     * 我们在这里使用测试工具(例如postman)进行测试
     * 实现签到功能
     * @return 返回值
     */
    @PostMapping("/api/user/sign")
    public Result sign() {
    	// 具体实现方法我们放到Impl中进行实现,不在controller中进行过多的代码编写
        return userService.sign();
    }

2. 具体实现代码

    /**
     * 用户签到功能
     * @return 返回值
     */
    @Override
    public Result sign() {
        // 1. 获取当前登录用户id
        Long userId = UserHolder.getUser().getId();
        // 2. 获取日期
        LocalDateTime now = LocalDateTime.now();
        // 3. 拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = "sign:" + userId + keySuffix;
        // 4. 获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        // 5. 写入redis  
        /**
         * 第一个参数:key,这没什么好说的,因为redis就是 key - value进行存储的(但是这个key是与现实中的月相关联的,也就是不同的月份key是不同的)
         * 第二个参数: 这个位置是向哪个位置插入数据 这里减 1 的原因是因为redis是从0开始进行存储的,加入我们是第一天,对应到redis为下标为0
         * 第三个参数: 填写 true或者false,代表 1或者0
         */
        stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
        return Result.ok();
    }

进行测试

  1. 发送请求(这里我进行了token验证,根据自己情况来)
    image
  2. 查看redis结果
    image
    因为我是在2022年11月15日进行测试,所以key是正确的,前面的1011是用户id,202211正确。下面为什么这么多0?因为redis不是根据位来进行存储的,而是字节存储形式, 一个字节8位,所以不满8的倍数的,自动补齐0。而1是第十五个位置,测试正确!!!

关于上面的一些用法说明

  • 为什么使用StringRedisTemplate而不是使用RedisTemplate。因为如果使用RedisTemplate的话,它会在我们存储对象信息的时候,会自动添加一行关于类的来源信息,因为RedisTemplate在对象与Json转换的时候不需要我们进行手动配置,但是它需要消耗我们的内存。
在简历中介绍使用Redis中的bitmap结构实现签到功能时,可以按照以下步骤进行: 1. 简单介绍RedisBitmap:首先简单介绍Redis是一个内存数据存储系统,而BitmapRedis提供的一种数据类型,它可以用于存储一系列的二进制标记,非常适合于需要高效处理二进制标记的场景。 2. 说明签到功能需求:接下来简要说明签到功能的需求,例如需要记录用户在某个时间点是否签到,以及需要对签到情况进行统计和分析等。 3. 介绍Bitmap实现签到的方法:接着详细介绍如何使用Redis中的Bitmap结构实现签到功能,包括创建Bitmap、更新用户签到状态、查询用户签到状态、统计签到人数等步骤,以及如何利用Bitmap进行高效的位运算和统计计算。 4. 突出技术优势和实现效果:在介绍的过程中可以突出Redis中的Bitmap结构相对于其他存储方式的优势,比如空间占用少、查询速度快等,并可以列举一些实际的实现效果,比如能够支持海量用户的高并发访问、能够满足秒级响应要求等。 5. 强调自己的经验和贡献:最后可以适当强调自己在该项目中的经验和贡献,例如设计并实现了高效的签到功能,优化了性能,提高了用户体验等。 一个简短的例子: 使用Redis中的bitmap结构实现了一个高效的签到功能。通过创建一个bitmap,每个用户对应bitmap中的一位,当用户签到时,将该位设为1,查询用户是否签到时,只需要查询该位是否为1,可以快速完成操作。在统计签到人数时,只需要对整个bitmap进行位运算即可。该方法占用空间较小,查询速度较快,能够支持海量用户的高并发访问,同时也满足秒级响应要求。我在该项目中设计并实现了高效的签到功能,并优化了性能,提高了用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值