Redis:原理速成+项目实战——Redis实战14(BitMap实现用户签到功能)

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:Redis:原理速成+项目实战——Redis实战13(GEO实现附近商铺、滚动分页查询)
📚订阅专栏:Redis:原理速成+项目实战
希望文章对你们有所帮助

用户签到是各个APP一个重要的功能,可以促进用户对APP的使用,所以用户签到,以及连续签到天数的统计都是很重要的。
这里将会基于BitMap(位图)来实现用户签到,而Redis刚好支持BitMap的数据结构。

BitMap实现用户签到

  • BitMap功能
  • 实现签到功能
  • 统计连续签到

BitMap功能

用一张表来存储用户签到信息:
在这里插入图片描述
多个用户、连续多天,会有很多的签到数据,这样的设计会占用太大的内存,对数据库的压力也很大。
解决方法:用位图(BitMap)来实现,最大用31bit即可统计一个用户一个月的签到记录。按月来统计用户签到信息,签到记录为1,否则为0。
Redis中利用String类型的数据结构实现BitMap,因此最大上限是512M,转换为bit则是2^32bit,32个bit位完全足够完成一个月的签到。
BitMap操作命令:

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

例如:

SETBIT bm1 0 1 # 给bm1的第0个位置设为1,表示第1天签到了(没有签到的话直接不用写语句,默认为0)
GETBIT bm1 2 # 查询第3天有没有签到
BITCOUNT # 查询共签到了几天
BITFIELD bm1 GET u2 0 # 从第一天开始算,获取2个bit位,并以无符号十进制整数返回
BITPOS bm1 0 # 第一个0出现的位置(第一次断签)

实现签到功能

发起Post请求,实现签到接口,将当前用户当天的签到信息保存到Redis中(key要包含用户以及日期信息(只需要年月))。而用户、当天时间,这些东西根本不需要前端来传,所以这是没有参数的接口。
因为BitMap底层是基于String的,因此相关操作也被封装到字符串相关操作中。

UserController:

	@PostMapping("/sign")
    public Result sign(){
        return userService.sign();
    }

UserServiceImpl:

    @Override
    public Result sign() {
        //获取当前登录用户
        Long userId = UserHolder.getUser().getId();
        //获取当前日期
        LocalDateTime now = LocalDateTime.now();
        //将用户与日期拼接成key,日期只需要年月的字符串格式
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + keySuffix;//"sign:"
        //获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //写入Redis SETBIT key offset 1
        stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
        return Result.ok();
    }

打开postman来测试接口:
在这里插入图片描述
查看Redis,今天1月13日,所以在坐标12标识为1,并且后面补0,补到字节整数倍(2字节16位)
在这里插入图片描述

统计连续签到

需求:统计本月到今天为止的连续签到次数,今天要是没签到直接就为0。

从最后一次签到开始向前统计,直到第一次未签到为止,总的签到次数即为连续签到天数。
剩下就是一个非常简单的模拟:

1、获取本月为止所有签到数据(BITFIELD key GET u[dayOfMonth] 0)
2、用1来做与运算,得到最后一个bit位
3、右移,即可获得下一个bit位

UserController:

	@GetMapping("sign/count")
    public Result signCount(){
        return userService.signCount();
    }

UserServiceImpl:

	@Override
    public Result signCount() {
        //获取当前登录用户
        Long userId = UserHolder.getUser().getId();
        //获取当前日期
        LocalDateTime now = LocalDateTime.now();
        //将用户与日期拼接成key,日期只需要年月的字符串格式
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + keySuffix;//"sign:"
        //获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //获取本月截止今天位置的所有签到记录,返回十进制数字
        List<Long> result = stringRedisTemplate.opsForValue().bitField(
                key,
                //设置为无符号数,且从第0位开始算,抽取出到今天为止的bit位
                BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
        );
        if(result == null || result.isEmpty()){
            return Result.ok(0);
        }
        //与1做与运算,得到数字的最后一个bit位
        Long num = result.get(0);
        if(num == 0 || num == null){
            //为0,未签到,结束
            return Result.ok(0);
        }
        //为1,循环遍历,为1则计数器+1
        int count = 0;
        while (true){
            if((num & 1) == 1){
                count++;
                num >>>= 1;//无符号右移1位
            }else{
                break;
            }
        }
        return Result.ok(count);
    }

打开postman做测试:
在这里插入图片描述
正式完成,这一部分的内容还是很基础的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/316873.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络——应用层(3)

计算机网络——应用层&#xff08;3&#xff09; 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 点对点&#xff08;P2P&#xff09;P2P网络一般用途优点缺点总结 套接字编程基本步骤UDP套接字TCP套接字基本步骤 二者对比 小程一言 我的计算机网络专栏&#xff0c;是自…

从数据可视化到场景渲染:山海鲸的创新与实践

作为山海鲸的开发者&#xff0c;我们深知可视化模型场景渲染在数据分析和决策支持中的重要作用。因此在保证山海鲸可视化软件免费编辑、分享、部署的同时也在场景渲染方面不断优化&#xff0c;本文将介绍山海鲸在可视化模型场景渲染方面的技术革新与实践探索。 首先&#xff0…

USB_CH340一键下载电路

目录标题 1、CH340概述2、CH340芯片特点3、CH340系列芯片4、CH340引脚定义5、CH340传统的一键下载电路5.1、Stm32串口下载5.2、ESP32串口下载5.3、注意 6、免外围电路下载 1、CH340概述 CH340是一个USB总线的转接芯片&#xff0c;可实现USB转串口或者USB转打印口。 2、CH340芯…

不要再搞混标准化与归一化啦,数据标准化与数据归一化的区别!!

数据标准化与归一化 1. 数据的标准化&#xff08;Standardization&#xff09;&#xff1a;2. 数据的归一化&#xff08;Normalization&#xff09;&#xff1a;总结&#xff08;数据标准化和数据归一化的不同之处和相同之处&#xff09; 1. 数据的标准化&#xff08;Standardi…

2024趋势:ERP中数据分析的五大要点

2024 年&#xff0c;数据分析不仅仅是 ERP 实施中的一个额外功能;这就像第一步&#xff0c;将最终确定整个 ERP 实施项目的成功之路。忘记笨重的电子表格和无休止的报告——准备好驾驭这五种新兴趋势的浪潮&#xff1a; 一、人工智能和机器学习 (ML) 的兴起 人工智能驱动的数据…

由于找不到vcomp140.dll无法继续执行代码如何修复-亲测有效

本文将详细介绍vcomp140.dll的定义、作用以及丢失的原因和解决方法。 一、vcomp140.dll是什么&#xff1f; vcomp140.dll是Visual C 2015 Redistributable Package的一部分&#xff0c;它是运行某些基于C的应用程序所必需的动态链接库文件。它包含了许多用于支持C编程语言的函…

Go-安装与基础语法

TOC 1. Go 安装与环境变量 1.1 下载 需要从Go语言的官方网站下载适合你操作系统的Go语言安装包。Go语言支持多种操作系统&#xff0c;包括Windows、Linux和Mac OS。 对于Windows用户&#xff0c;下载.msi文件&#xff0c;然后双击该文件&#xff0c;按照提示进行安装即可。…

PADS9.5 : 元件库绘制

元件库绘制 1、打开PADS LOGIC 软件 2、先开始元件的电参数 这理面我们只需要先关注&#xff1a; 门 &#xff0c;就是当前画的元件有几个部分 示例&#xff1a;两个门&#xff1a;A、B 3、再开始编辑图形 选择创建2D线&#xff0c;绘制PARTA 外框 添加端点&#xff0c;就是接…

5.3 Verilog 带参数例化

5.3 Verilog 带参数例化 分类 Verilog 教程 关键词&#xff1a; defparam&#xff0c;参数&#xff0c;例化&#xff0c;ram 当一个模块被另一个模块引用例化时&#xff0c;高层模块可以对低层模块的参数值进行改写。这样就允许在编译时将不同的参数传递给多个相同名字的模块…

通过代理连接sftp

通过nginx代理连接sftp 1.问题描述2.代码实现3.nginx配置3.1 创建sftp.stream文件3.2 修改nginx配置 4.重启nginx生效 1.问题描述 问题是这样的。我们现在需要在微服务所在内网的A机器连接到外网的sftp&#xff0c;但是网络又不能直接到达。然后A机器到B机器是通过的&#xff…

我开源了一个 Go 学习仓库

前言 大家好&#xff0c;这里是白泽&#xff0c;我是21年8月接触的 Go 语言&#xff0c;学习 Go 也正好两年半&#xff0c;我决定重启我之前未完成的计划&#xff0c;继续阅读《The Go Programing Language》&#xff0c;一年多前我更新至第五章讲解的时候&#xff0c;工作的忙…

浅谈当下企业环境下建设企业微电网能效系统的重要性

一 案例介绍 随着新型电力系统进程加快&#xff0c;新能源装机占比逐步提高&#xff0c;发电侧波动性、随机性导致可靠容量降低。加之恶劣天气带动负荷快速增长&#xff0c;造成电力供需紧张、电网尖峰负荷屡创新高&#xff0c;对现有能源供应带来巨大挑战。 国家电投五凌电…

新手入门:软件在测试过程中可能出现哪些问题?走,去看看~

对于很多测试新手来说&#xff0c;想要把自己的测试技术练得更精进&#xff0c;扎实自己的理论知识是必不可少的一门功课。下面&#xff0c;我们就一起来复习一下&#xff0c;那些让我们一知半解或者记不全的理论知识吧。 01 什么是软件测试&#xff1f; 最老套&#xff0c;但…

手写Webpack-Plugin

Plugin原理 一、Plugin作用 通过插件我们可以扩展webpack&#xff0c;使webpack可以执行更广泛的任务&#xff0c;拥有更强的构建能力。 Plugin工作原理 webpack 就像一条生产线&#xff0c;要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程…

LeetCode讲解篇之90. 子集 II

文章目录 题目描述题解思路题解代码 题目描述 题解思路 初始化一个变量start表示当前从哪里开始遍历nums 搜索过程的数字组合加入结果集 从start开始遍历nums 如果当前元素和前一个元素相等&#xff0c;前一个元素没被使用&#xff0c;则触发剪枝去重操作&#xff0c;跳过当…

[蓝桥学习] 并查集

并查集基础 并查集用来存储图中结点的连通关系。 一个点的根结点是该点的父亲的父亲的...父亲&#xff0c;根&#xff1a;某个结点的父亲是自己 当两个点的根相同时&#xff0c;就说他们是同一类的&#xff0c;连通的 找根 但是&#xff0c;如果点特别多且形成链的话&#x…

【MySQL】本地创建MySQL数据库详解

文章目录 下载MySQL安装重置密码本地连接 下载MySQL 下载网址&#xff1a;https://dev.mysql.com/downloads/mysql/ 安装 将下载好的压缩包解压到D盘。 在解压好的文件夹中创建my.ini文件。 将以下代码复制粘贴到创建好的my.ini文件中。注意修改文件路径。 [mysqld] #设置…

2024/1/14周报

文章目录 摘要Abstract文献阅读题目问题与创新方法A.CEMDAN方法B.LSTM网络C. CEEMDAN-LSTM模型 实验过程数据集与数据预处理参数设置评价指标和参数 实验结果 深度学习GRUGRU前向传播GRU的训练过程 总结 摘要 本周阅读了一篇基于CEEMDAN-LSTM的金融时间序列预测模型的文章&…

FineBI实战项目一(22):各省份订单个数及订单总额分析开发

点击新建组件&#xff0c;创建各省份订单个数及订单总额组件。 选择自定义图表&#xff0c;将province拖拽到横轴&#xff0c;将cnt和total拖拽到纵轴。 调节纵轴的为指标并列。 修改横轴和纵轴的标题。 修改柱状图样式&#xff1a; 将组件拖拽到仪表板。 结果如下&#xff1a;…

windows同时安装mysql5.0和8.0步骤(完美测试)

mysql5.0和mysql8.0配置如下 1.把如下配置复制下替换到my.ini中 mysql5.0配置如下 [mysqld] # 设置3306端口 port3306 # 设置mysql的安装目录 basedirF:\mysql-5.7.38 # 设置mysql数据库的数据的存放目录 datadirF:\mysql-5.7.38\data # 允许最大连接数 max_connections200 #…