Redis实现用户签到

2023-11-03

目录

一、BitMap用法

1、介绍

2、用法

3、练习

二、签到功能

1、需求

2、代码实现

三、签到统计

1、分析

2、接口实现


一、BitMap用法

1、介绍

我们完全可以通过数据库签到表来实现签到功能,但是假如我们的用户达到千万,每年平均签到10次,则这张表一年的数据为1亿条。

我们可以按月来统计用户签到信息,签到记为1,未签到记录为0,我们可以用31位的二进制数表示一个月的签到数据。31bit只需要两个字节,把每一个bit位对应当月的每一天,形成了映射关系。用0和1标识业务状态,这种思路就成为位图(BitMap)

Redis中利用String类型数据结构实现BitMap。因此最大上限是512M,转换为bit则是2^32个bit位

2、用法

BitMap 的操作命令有:

  • SETBIT:向指定位置(offset)存入一个 0 或 1
  • GETBIT:获取指定位置(offset)的 bit 值
  • BITCOUNT:统计 BitMap 中值为 1 的 bit 位的数量
  • BITFIELD:操作(查询、修改、自增)BitMap 中的 bit 数组中的指定位置(offset)的值。关于BITFIELD 命令的详细介绍可以看下这篇文章bitfield 命令
  • BITFIELD_RO:获取 BitMap 中的 bit 数组,并以十进制形式返回
  • BITOP:将多个 BitMap 的结果做位运算(与、或、异或)
  • BITPOS:查找 bit 数组中指定范围内第一个 0 或 1 出现的位置

3、练习

设置签到,默认是从0开始的

获取第三天的签到数据

获取总的签到次数

使用 BITFIELD 命令获取数据:从 0 号位开始获取两个 bit 位(读多个,返回10进制)

type表示类型参数:当被设置的二进制位范围值为整数时,用户可以在类型参数的前面添加 i 来表示有符号整数,或者使用 u 来表示无符号整数。比如说,我们可以使用 u8 来表示 8 位长的无符号整数,也可以使用 i16 来表示 16 位长的有符号整数。 

查找 bit 数组中指定范围内第一个 0 或 1 出现的位置:

二、签到功能

1、需求

实现签到接口,将当前用户当天签到信息保存到redis中

因为是知道当天当天用户就行,所有是接口是无参的

提示:BitMap底层是基于String数据结构,因此操作封装在字符串相关操作中

2、代码实现

Service的方法

三、签到统计

1、分析

什么叫连续签到的天数?

从最后一次签到开始向前统计,直到遇到第一次未签到为止,计算总的签到次数

如何得到本月到今天为止的所有签到数据?

使用命令:BITFIELD key GET u[dayOfMonth] 0 

u代表无符号,后面跟的数字是多少位,今天是多少号取多少位,最后的0是起始位置

如何从后向前遍历每个bit位?

与1做与运算,就能得到最后一个bit位

然后把数字右移1位,下一个bit位就成为最后一个bit位,重复与1与运算

然后重复这样,就能遍历完

2、接口实现

实现接口,统计当前用户截止至当前时间本月连续签到天数

(请求参数也是无,就用当前用户和当前时间就能查)

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

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

	@Override
    public Result signCount() {
        // 获取当前登录用户
        Long userId = UserHolder.getUser().getId();
        // 获取当前日期
        LocalDateTime now = LocalDateTime.now();
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        // 拼接 key
        String key = USER_SIGN_KEY + userId + keySuffix;
        // 获取今天是本月的第几天
        // 当前日期为 2022年5月12号,故而 dayOfMonth = 12
        int dayOfMonth = now.getDayOfMonth();
        // 获取从 0 到 dayOfMonth 的签到结果
        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);
        }
        Long num = result.get(0);
        if (num == null || num == 0) {
            return Result.ok(0);
        }

        int count = 0;
        // 循环遍历
        while(true){
            // 让这个数字与 1 做与运算,得到数字的最后一位 bit 位  判断这个 bit 位是否为0
            // num & 1 做与运算,其中 1 的左边以 0 补齐
            if ((num & 1) == 0) {
                // 如果为 0,说明未签到,结束
                break;
            } else {
                // 如果不为 0,说明已签到,计数器 +1
                count++;
            }
            // 把数字右移一位,抛弃最后一个 bit 位,继续下一个 bit 位
            // >> :右移 最高位是0,左边补齐0;最高为是1,左边补齐1
            // << :左移 左边最高位丢弃,右边补齐0
            // >>>:无符号右移 无论最高位是0还是1,左边补齐0
            // num >>>= 1 ————> num = num >>> 1
            num >>>= 1;
        }
        return Result.ok(count);
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis实现用户签到 的相关文章

  • 为什么我不能让单个 Redis 客户端在同一连接中充当 PUB 和 Sub ?

    我的思维模型是 聊天 我订阅了某个频道 并且可以向该频道发布消息 由于 pub sub 是异步的 因此发布的消息可能随时出现 包括当您期望命令响应时 尽管 Redis 是单线程的 通常会阻止此类事情 但网络延迟可能会导致一些有趣的影响 根据
  • 使用 sidekiq 处理两个独立的 Redis 实例?

    下午好 我有两个独立但相关的应用程序 他们都应该有自己的后台队列 阅读 单独的 Sidekiq 和 Redis 进程 然而 我希望偶尔能够将工作推给app2的队列来自app1 从简单的队列 推送的角度来看 如果app1没有现有的 Sidek
  • AWS Redis 从外部连接

    有没有办法从外部 AWS 网络连接 AWS 上托管的 Redis 实例 我有一个基于 Windows 的 EC2 实例在 AWS 上运行 另一个是 Redis 缓存节点 我知道有人问过这个问题 但答案是在基于 Linux 的系统中 但我的是
  • Laravel - 缓存 Eloquent 并频繁更新

    是否可以对经常修改的对象使用缓存 例如 假设我们有一个 BlogPost 对象 并且有一个经常更改的 num of views 列 以及其他列 是否可以更新缓存和数据库中的 num of views 字段 而不破坏缓存对象并重新创建它 我可
  • Spring RedisTemplate:8次调用后方法键挂起

    我使用 Spring RedisTemplate spring data redis 1 7 1 与 Redis 进行通信 我需要通过正则表达式获取然后删除键 例如 context user1 我用的方法 RedisTemplate key
  • python 3.5 中的 json.loads 和 Redis

    我使用 json dumps 创建了一个 JSON 对象 并在 Redis 列表中将其 RPUSH ed 当使用 LRANGE redis lrange 返回 JSON 时 我收到一个二进制字符串 b si 00 ff 所以 json lo
  • 如何在节点redis客户端上设置读取超时?

    在 github 上我没有看到读取超时的选项 https github com NodeRedis node redis https github com NodeRedis node redis There s connect timeo
  • WSL Redis 遇到系统尚未使用 systemd 作为 init 系统(PID 1)启动。无法操作[已关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在尝试遵循本文中讨论的 Redis 安装过程article https www digitalocean com community
  • redis-cli 重定向到 127.0.0.1

    我在PC1上启动Redis集群 然后在PC2上连接它 当需要重定向到另一个集群节点时 它会显示Redirected to slot 7785 located at 127 0 0 1 但应该显示Redirected to slot 7785
  • 如何将node.js管道传输到redis?

    我有很多数据要插入 SET INCR 到redis DB 所以我正在寻找pipeline http redis io topics pipelining 质量插入 http redis io topics mass insert通过node
  • socket.io 广播功能 & Redis pub/sub 架构

    如果有人能帮助我解决一个小疑问 我将不胜感激 使用socket io广播功能和在Redis上使用pub sub设计架构有什么区别 例如 在另一个示例中 node js 服务器正在侦听 socket io 针对 键 模型 todo 和值 数据
  • Redis发布/订阅:查看当前订阅了哪些频道

    我目前有兴趣查看我拥有的 Redis 发布 订阅应用程序中订阅了哪些频道 当客户端连接到我们的服务器时 我们将它们注册到如下所示的通道 user user id 这样做的原因是我希望能够看到谁 在线 目前 我在不知道客户端是否在线的情况下盲
  • 如何在Redis中从hmset()切换到hset()?

    我收到弃用警告 即 Redis hmset 已弃用 请改用 Redis hset 但是 hset 采用第三个参数 我不知道是什么name应该是 info users 10 timestamp datetime utcnow strftime
  • Lua中按字符分割字符串

    我有像这样的字符串 ABC DEF 我需要将它们分开 字符并将两个部分分别分配给一个变量 在 Ruby 中 我会这样做 a b ABC DEF split 显然Lua没有这么简单的方法 经过一番挖掘后 我找不到一种简短的方法来实现我所追求的
  • Redis Cluster 与 Pub/Sub 中的 ZeroMQ,用于水平扩展的分布式系统

    如果我要设计一个巨大的分布式系统 其吞吐量应随系统中的订阅者数量和通道数量线性扩展 哪个会更好 1 Redis集群 仅适用于Redis 3 0 alpha 如果是集群模式 您可以在一个节点上发布并在另一个完全不同的节点上订阅 消息将传播并到
  • Java 将字节转换为二进制安全字符串

    我有一些以字节为单位的数据 我想将它们放入Redis中 但是Redis只接受二进制安全字符串 而我的数据有一些二进制非安全字节 那么如何将这些字节转换为二进制安全字符串以便将它们保存到 Redis 中呢 Base64 对我有用 但它使数据更
  • Redis、会话过期和反向查找

    我目前正在构建一个网络应用程序 并想使用 Redis 来存储会话 登录时 会话会使用相应的用户 ID 插入到 Redis 中 并且过期时间设置为 15 分钟 我现在想实现会话的反向查找 获取具有特定用户 ID 的会话 这里的问题是 由于我无
  • 有没有办法让特定的key在集群模式下定位到特定的redis实例上?

    我想让我的多锁位于不同的redis实例上 我发现redission可以指定一个实例来执行命令 但是如果该命令与key相关 则指定的实例会将命令传输到另一个实例 你能给我一些建议吗 你可以 但这并不是微不足道的 首先 Redis 在键中使用大
  • 使用 Celery 通过 Gevent 进行实时、同步的外部 API 查询

    我正在开发一个 Web 应用程序 该应用程序将接收用户的请求 并且必须调用许多外部 API 来编写对该请求的答案 这可以直接从主 Web 线程使用 gevent 之类的东西来扇出请求来完成 或者 我在想 我可以将传入的请求放入队列中 并使用
  • 如何使redis中的“HSET”子键“过期”?

    我需要使 Redis 哈希中所有超过 1 个月的密钥过期 这不可能 https github com antirez redis issues 167 issuecomment 2559040 为了保持 Redis 简单 https git

随机推荐

  • C++ NUM4

    c 数字 c 内置丰富的数学函数 引用数学头文件
  • Tkinter(二) | 点击按钮显示图片

    解决办法 出现的问题 from tkinter import from PIL import Image ImageTk root Tk root title 按钮点击加载图片 def show img Image open 1 png 打
  • Java中接口中的方法定义规范

    1 接口中是可以定义静态方法的 静态方法必须要有实现 且这个静态方法只能用public修饰 例如 public static void test 或 static void test public省略不写默认也是用public来修饰 静态方
  • 服务计算——Docker 简单使用

    Docker 简单使用 Docker是一个应用容器引擎 使用者可以将其应用以及所有需要的依赖打包到一个包中 然后发布到机器上进行运作 接下里我们就一步步了解一些Docker的使用 Docker安装 sudo apt get install
  • STM32-GPIO输入

    点亮LED灯的实验室利用的GPIO的输出配置来实现的 接下来写一个关于GPIO作为输入的程序 同时点亮和熄灭LED灯 由于程序简单 直接贴出代码 以供参考 include stm32f10x h brief 初始化GPIO 默认速度为GPI
  • 判断英伟达显卡计算力及是否支持FP16和INT8

    文章目录 1 检查显卡的计算力 打开 官网 检查你相应型号显卡的算力 比如GTX1080 is 6 1 Tesla T4 is 7 5 2 检查是否支持FP16和INT8 打开网页查看
  • Python 3.11.3在Windows 11下的简易安装教程

    撰写时间 2023年4月6日 本文目的 帮助电脑小白快速安装最新版本的Python 并通过控制台输出第一个Python语句 Hello World 前言 Python是一种高级编程语言 具有简单易学 代码简洁 功能强大 可移植性佳等特点 由
  • 《30天自制操作系统》harib09c的编译和调试

    今天是 30天自制操作系统 学习的第12天 今天的工程目录是harib09c 我起的目录名称是day12 boyC 我们一起来调试一下 在day12 boyC目录下直接运行make命令就开始编译了 如下图所示 编译的结果如下 部分截取 E
  • Java Interface

    Java接口中的成员变量的修饰符都是 public的 static的 final 的 类这么写错的 一个类不能既是final 又是abstract的 因为abstract 因为类被继承使用 而 final却不允许类被继承 这是自相矛盾的 p
  • 从零开始学WEB前端——VUE脚手架

    项目介绍 先做个自我介绍 本人是一个没人写前端所以就自学前端的后端程序员 在此项目中我会和大家一起从零基础开始学习前端 从后端程序员的视角来看前端 受限于作者的水平本项目暂时只会更新到前端框架VUE 不会涉及node js 该项目适合零基础
  • Nginx安装、配置

    一 Nginx概述 特点 Nginx engine x 是一个轻量级的 高性能的 基于Http的 反向代理服务器 静态web服务器 具有以下特点 1 高并发 一个Nginx服务器在不做任何配置的情况下并发量可达1000左右 在硬件条件允许的
  • unity hub突然打不开,解决记录

    1 情况 管理员身份运行无效 从unity cn下载安装无效 从unity com下载安装无效 2 失败原因 安装的时候一直用的之前的安装路径 始终打不开 3 解决 换了新的安装路径 成功解决
  • 开源进展|WeCross v1.3.0发布,支持适配FISCO BCOS v3.0

    WeCross是微众银行自主研发并完全开源的区块链跨链协作平台 致力于促进跨行业 机构和地域的跨区块链信任传递和商业合作 有助于实现异构区块链系统之间安全可信的互操作 WeCross v1 2 0自发布以来 得到了众多社区伙伴的支持和反馈
  • BlogTest1

    常见数据结构题 SparseArray SparseBooleanArray HashMap
  • 安防监控视频云存储平台EasyNVR出现内核报错的情况该如何解决?

    安防视频监控汇聚EasyNVR视频集中存储平台 是基于RTSP Onvif协议的安防视频平台 可支持将接入的视频流进行全平台 全终端分发 分发的视频流包括RTSP RTMP HTTP FLV WS FLV HLS WebRTC等格式 近期有
  • 【全教程】Pycharm运行深度强化学习代码(pytho与matlab混编)

    记录自己运行的第一个深度强化学习项目的全过程 配置环境花了4h 代码终于跑起来啦 配置环境 下面是具体的配置流程 首先报的第一个错误是 ModuleNotFoundError No module named matlab engine ma
  • Arduino和LabVIEW射频灾害紧急报警系统

    该项目将在发生灾难时生成紧急警报 该系统分为两部分 传感器节点和 2 服务器 连接该开关阵列以在处理端生成紧急信号 然后将其发送到传感器节点 图1给出了系统框图 物料清单 接线 原理图 代码 传感器节点端代码 处理端代码 仿真模型 LabV
  • 【实验五】【创建视图并通过视图操作表数据】

    文章目录 视图 原表 一 创建视图 二 插入数据 三 更新数据 四 删除数据 Reference 视图 简介 视图可以看作定义在SQL Server上的虚拟表 视图正如其名字的含义一样 是另一种查看数据的入口 常规视图本身并不存储实际的数据
  • 渗透第一步之DNS信息收集技巧。

    正向查询 首先 最简单最快速的是 使用ping命令输入域名来获取其ip地址 或者 使用nslookup命令来指定域名获取ip地址 Server 192 168 90 83 DNS服务器 Address 192 168 90 83 我们解析到
  • Redis实现用户签到

    目录 一 BitMap用法 1 介绍 2 用法 3 练习 二 签到功能 1 需求 2 代码实现 三 签到统计 1 分析 2 接口实现 一 BitMap用法 1 介绍 我们完全可以通过数据库签到表来实现签到功能 但是假如我们的用户达到千万 每