Redis-用户签到UV统计

news2024/12/30 3:33:06

一、用户签到

1.1 BitMap用法

我们按月来统计用户签到信息,签到记录为1,未签到记录为0
在这里插入图片描述
把每一个bit位对应当月的每一天,形成了映射关系。用0和1表示业务状态,这种思路就称为位。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出现的位置;

1.2 签到功能

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

public Result sign() {
   // 1. 获取当前登录用户
    Long userId = UserHolder.getUser().getId();
    // 2. 获取日期,拼接key
    LocalDateTime now = LocalDateTime.now();
    String key = USER_SIGN_KEY +
            userId +
            now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
    // 3. 获取今天是本月的第几天
    int dayOfMonth = now.getDayOfMonth();
    // 4. 写入 redis SETBIT key offset 1
    stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
    return Result.ok();
}

1.3 签到统计

问题1:什么叫做连续签到天数?

从最后一次签到开始向前统计,知道遇到第一次未签到为止,计算总的签到次数,就是连续签到次数
在这里插入图片描述

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

在这里插入图片描述

问题3:如何从后向前遍历每个bit位?

与1做与运算,就能得到最后一个bit位。
随后右移1位,下一个bit位就成为了最后一个bit位。

@Override
public Result signCount() {
    // 1. 获取当前登录用户
    Long userId = UserHolder.getUser().getId();
    // 2. 获取日期,拼接key
    LocalDateTime now = LocalDateTime.now();
    String key = USER_SIGN_KEY +
            userId +
            now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
    // 3. 获取今天是本月的第几天
    int dayOfMonth = now.getDayOfMonth();
    // 4. 获取本月截止今天为止的所有的签到记录,返回的是一个十进制的数字 BITFIELD sign:5:202203 GET u14 0
    List<Long> results = stringRedisTemplate.opsForValue().bitField(
            key,
            BitFieldSubCommands.create()
                    .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth))
                    .valueAt(0)
    );
    if (Objects.isNull(results) || CollectionUtils.isEmpty(results)) {
        return Result.ok(0);
    }
    Long num = results.get(0);
    if (Objects.isNull(num) || num == 0) {
        return Result.ok(0);
    }
    // 5. 循环遍历
    int count = 0;
    while (true) {
        // 6.1. 让这个数字与1做与运算,得到数字的最后一个bit位 // 判断这个bit位是否为0
        if ((num & 1) == 0) {
            // 如果为0,说明未签到,结束
            break;
        } else {
            // 如果不为0,说明已签到,计数器+1
            count++;
        }
        // 把数字右移一位,抛弃最后一个bit位,继续下一个bit位
        num >>>= 1;
    }
    return Result.ok(count);
}

二、UV统计

2.1 HyperLogLog用法

首先,我们搞懂两个概念:

  • UV: 全称Unique Visitor,也叫独立访客量,是指通过互联网访问、浏览这个网页的自然人。1天内同一个用户多次访问该网站,只记录1次。
  • PV: 全称Page View,也叫页面访问量或点击量,用户每访问网站的一个页面,记录1此PV,用户多次打开页面,则记录多次PV。往往用来衡量网站的流量。

UV统计在服务端做会比较麻烦,因为要判断该用户是否已经统计过了,需要将统计过的用户信息保存。但是每个访问的用户都保存到Redis中,数据量会非常恐怖

2.2 实现UV统计

我们直接利用单元测试,向HyperLogLog中添加100万条数据,看看内存占用和统计效果如何:

@Test
void testHyperLogLog() {
     String[] values = new String[1000];
     int j = 0;
     for (int i = 0; i < 1000000; i++) {
         j = i % 1000;
         values[j] = "user_" + i;
         if (j == 999) {
             // 发送到Redis
             stringRedisTemplate.opsForHyperLogLog().add("hl2", values);
         }
     }
     // 统计数量
     Long count = stringRedisTemplate.opsForHyperLogLog().size("hl2");
     System.out.println("count = " + count);
 }

运行结果:

count = 997593

查看内存(命令:info memory)

  • 插入数据之前
    在这里插入图片描述
  • 插入数据之后
    在这里插入图片描述
  • 计算
    (1396913 - 1366928)/ 1024
    在这里插入图片描述

2.3 总结

  • HyperLogLog的作用:
    • 做海量数据的统计工作
  • HyperLogLog的优点:
    • 内存占用极低;
    • 性能非常好;
  • HyperLogLog的缺点:
    • 有一定的误差

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用pip命令时,报错:_sysconfigdata_x86_64_conda_cos7_linux_gnu.py

问题&#xff1a; 在linux服务器中想使用pip命令pip show list查看安装了哪些包时&#xff0c;报错 ModuleNotFoundError: No module named ‘_sysconfigdata_x86_64_conda_cos7_linux_gnu’ 问题原因 原因是&#xff1a;在当前的环境下的python中丢失了一个备份文件&#xf…

经典算法之常用排序

目录❤️前言&#x1f498;一、分治思想&#x1f49e;二、归并排序1.实现方法2.动图分析3.代码模板&#x1f496;三、快速排序1.实现方法2.动图分析3.代码模板❤️前言 本文介绍两种基于分治思想的经典排序算法&#xff1a; 归并排序与快速排序 &#x1f498;一、分治思想 分…

【Python从入门到进阶】1、初识Python

一、Python的起源 1989年&#xff0c;为了打发圣诞节假期&#xff0c;荷兰程序员Gudio van Rossum吉多●范罗苏姆(龟叔&#xff0c;下图穿“人生苦短&#xff0c;我用Python”T恤衫的老哥)决心开发一个新的解释程序&#xff08;Python维形&#xff09;; 1991年&#xff0c;第一…

机器学习中的数学原理——向量内积

今天是2023年的第一天&#xff0c;祝大家新年快乐&#xff01;这个专栏主要是用来分享一下我在机器学习中的学习笔记及一些感悟&#xff0c;也希望对你的学习有帮助哦&#xff01;感兴趣的小伙伴欢迎私信或者评论区留言&#xff01;这一篇就更新一下《白话机器学习中的数学——…

【C语言】指针

文章目录指针作为参数的指针访问某个地址上的变量*指针的应用数组和指针数组变量是特殊的指针指针常量和常量指针数组指针和指针数组常见错误指针运算动态内存分配指针 一般用p来表示一个指针&#xff0c;来自pointer 一个指针类型的变量就是保存地址的变量。 变量的值是内存…

windows x32调用门实现 ring3提权

概述 调用门是Intel提供的一个机制&#xff0c;用于控制不同权限级(ring0-ring3)的程序函数调用。简单点就是提供了一个ring3 调用ring0 函数的机制。 在intel手册volume3-Chapter 5.83描述如下 Call gates facilitate controlled transfers of program control between dif…

算法笔记(25)win10系统安装tensorflow-GPU环境亲测好用

环境准备 首先你的电脑得有GPU显卡&#xff0c;然后在tensorflow官网&#xff08;在 Windows 环境中从源代码构建 | TensorFlow&#xff09;找到各安装软件对应的版本&#xff0c;版本不对应将会导致安装失败。 标本机GPU显卡版本题本文选择的是官网最新的组合&#xff1a;p…

cubeIDE开发, stm32窗口看门狗WWDG的CubeMX配置及HAL库底层实现分析

一、stm32的WWDG说明 1.1 WWDG特点&#xff1a; 在前一篇博文介绍独立看门狗时就指出STM32 MCU提供两个看门狗&#xff0c;独立看门狗和窗口看门狗。 cubeIDE开发&#xff0c; stm32独立看门狗IWDT的CubeMX配置及HAL库底层实现分析_py_free的博客-CSDN博客 相比独立看门狗&am…

【C语言】数据类型

文章目录c语言的类型整数整数类型整数的内部表达整数的范围unsigned整数的格式化浮点型浮点类型输入输出输出精度字符类型逃逸字符类型转换自动类型转换强制类型转换逻辑类型bool逻辑运算条件运算符C语言的变量&#xff0c;必须在使用前定义&#xff0c;并且确定类型&#xff1…

ubuntu下使用doxygen生成软件文档

ubuntu下使用Doxygen生成软件文档一、软件下载1.系统安装Doxygen2.Vscode插件安装二、软件配置三、文档生成1.方法1&#xff1a;使用Doxygen-gui生成&#xff08;推荐&#xff09;2.方法&#xff1a;采用Doxygen命令&#xff08;不推荐&#xff09;另外Windows下使用方法提示&a…

【JavaScript】 Date 日期对象概述及相关方法

文章目录【JavaScript】 Date 日期对象的创建及相关方法一. 日期对象的创建二. 日期对象的相关方法三. 时间戳案例案例1&#xff1a;在页面上展示一个时钟&#xff0c;隔1s更新一次案例2&#xff1a;距离除夕倒计时【JavaScript】 Date 日期对象的创建及相关方法 一. 日期对象…

ArcGIS基础:构建点对连线表达点集内部相互关系

原始数据如下&#xff0c;为普通的点图层&#xff0c;总共是21个点。 点位分布如下&#xff1a; 属性表打开如下&#xff1a; 下面使用【构造视线】工具进行操作&#xff0c;其工具位于【3D分析工具】下的【可见性】工具栏。 打开【构造视线】对话框&#xff0c;把【视点…

Leetcode【494. 目标和】

题目描述 给你一个整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 ‘’ 或 ‘-’ &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 例如&#xff0c;nums [2, 1] &#xff0c;可以在 2 之前添加 ‘’ &#xff0c;在 1 之前添加 ‘-’ &…

第10章 角色页的分页、排序、查询实现

1 重构WebApi.Controllers.RoleController. PostRolePageByFromBodyAsync //把所有符合条件的角色实例&#xff0c;按照指定字段进行排序操作。 if (!string.IsNullOrEmpty(pagination.OrderByFiled)) { var _obj JsonConvert.DeserializeAnonymousType(pagination.OrderByFil…

力扣 2351. 第一个出现两次的字母

题目 给你一个由小写英文字母组成的字符串 s &#xff0c;请你找出并返回第一个出现 两次 的字母。 注意&#xff1a; 如果 a 的 第二次 出现比 b 的 第二次 出现在字符串中的位置更靠前&#xff0c;则认为字母 a 在字母 b 之前出现两次。 s 包含至少一个出现两次的字母。 …

TopK问题的必会解法

目录经典解法&#xff0c;创建K个大小的堆不考虑空间的暴力排序做法不考虑空间的快排partition变形减治法思想(核心&#xff1a;找第K大的数)空间有限放不下&#xff0c;海量数据的分治法经典解法&#xff0c;创建K个大小的堆 传统的直接建立一个K个元素的小顶堆&#xff0c;类…

推荐两款可以将图片无损放大的在线工具

文章目录一、waifu2x网站预览传送地址二、BigJPG网站预览传送地址好不容易找到合适的图片素材但尺寸太小&#xff1f;那这里的工具正好适合你&#xff0c;能把你的小图放大几倍都不模糊。 一、waifu2x 本程序使用卷积神经网络对动漫风格的图片进行放大操作&#xff08;支持照…

再聊一下那 SQLSERVER 行不能跨页的事

一&#xff1a;背景 1. 讲故事 上一篇写完了之后&#xff0c;马上就有朋友留言对记录行的 8060byte 限制的疑惑&#xff0c;因为他的表记录存储了大量的文章&#xff0c;存储文章的字段类型用的是 nvarchar(max)&#xff0c;长度很显然是超过 8060byte 的&#xff0c;请问这个…

win10搭建 IIS 服务器

第一步: 打开程序和功能 找到 Internet 这个 勾选web管理工具和万维网服务 第二步: 在本地电脑创建一个文件夹(不要有中文空格等特殊字符) index.html 是默认访问的网址 第三步 关联访问的链接 选择本地物理路径 访问测试 第四步 修改绑定端口 第五步 修改防火墙 …

Linux | 文件操作的系统调用 open() read() write()

1. 基本含义辨析 文件操作的系统调用 open read write close &#xff08;系统调用&#xff1a;实现在内核中【用户态->内核态】—“陷入内核”&#xff09; man&#xff1a; 1 命令 2 系统调用 3 库函数 C操作文件的库函数 fopen fread fwrite fclose &#xff08;fo…