(黑马点评)八、实现签到统计和uv统计

8.1 签到统计系列功能

8.1.1 认识BitMap结构

        BitMap是Redis基于String实现的一种高效的二进制数位的数据结构。因此一个BItMap的最大上线为512M,转为bit位可表示 2^32位

常见命令

SETBIT:向指定位置(offset)存入一个01

GETBIT :获取指定位置(offset)的bit

BITCOUNT :统计BitMap中值为1bit位的数量

BITFIELD :操作(查询、修改、自增)BitMapbit数组中的指定位置(offset)的值

BITFIELD_RO :获取BitMapbit数组,并以十进制形式返回

BITOP :将多个BitMap的结果做位运算(与 、或、异或)

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

 8.1.2 为什么要使用BitMap结构进行统计

传统的数据库表统计方式:十分耗费存储内存

采用二进制位的BitMap统计方式:高效、内存占用少、

key用来指定统计者的信息:姓名、编号、年月

vlaue采用二进制的0 | 1 串标识签到状况 ,0表示为未签到 1 表示为已签到

8.1.3 使用BitMap实现用户签到统计

按月来统计用户签到信息,签到记录为1,未签到则记录为0.

签到功能实现流程

1. 获取当前用户信息

2. 获取当前日期信息

3. 拼接业务key

4. 使用setBit(key,offset,value)实现签到打卡

    /*** 签到统计* @return*/@PostMapping("/sign")public Result sign(){return userService.sign();}/*** 签到功能* @return*/@Overridepublic Result sign() {//1. 获取当前的登陆用户UserDTO user = UserHolder.getUser();//2. 获取当前日期LocalDateTime now = LocalDateTime.now();//3. 拼接业务的keyString keySuffix = now.format(DateTimeFormatter.ofPattern("yyyy/MM"));String key =USER_SIGN_KEY +user.getNickName() +'_' + user.getId() +'_' + keySuffix;//4. 获取签到日期int day = now.getDayOfMonth();//5. 写入Redis SETBIT key offset ture/falsestringRedisTemplate.opsForValue().setBit(key, day-1, true);return Result.ok();}
直接发送签到请求

查看Redis写入的签到卡

 

8.1.4 使用BitMap实现用户连续签到天数统计

实现统计连续签到天数的流程

1. 获取当前登录用户信息

2. 获取日期信息

3. 拼接业务key

4. 使用 stringRedisTemplate.opsForValue()
                .bitField(key,
                        BitFieldSubCommands
                                .create()
                                .get(BitFieldSubCommands
                                        .BitFieldType
                                        .unsigned(dayOfMonth))
                                .valueAt(0)); 获取统计信息【10进制】

5. 判空

6. 循环右移 + 与1 运算 得出连续签到天数

7. 返回结果

/*** 连续签到天数统计* @return*/@GetMapping("/sign/count")public Result countSign(){return userService.countSign();}/*** 连续签到天数统计* @return*/@Overridepublic Result countSign() {//1. 获取当前登录用户UserDTO user = UserHolder.getUser();//2. 获取当前日期LocalDateTime now = LocalDateTime.now();int dayOfMonth = now.getDayOfMonth();//3.拼接业务的keyString keySuffix = now.format(DateTimeFormatter.ofPattern("yyyy/MM"));String key = USER_SIGN_KEY +user.getNickName() +'_' + user.getId() +'_' + keySuffix;//4. 获取当前用户签到数据(返回十进制数)List<Long> signNum = stringRedisTemplate.opsForValue().bitField(key,BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));if(signNum == null || signNum.isEmpty()){return Result.ok(0);}Long num = signNum.get(0);if(num == null || num == 0){return Result.ok(0);}//5. 循环右移 + 1与运算 得出连续签到天数int dayCount = 0;while(true) {if(((num & 1) == 0)){break;}else{dayCount ++;}num = num >> 1;}return Result.ok(dayCount);}
发送连续签到统计请求

 

8.2 百万级UV统计功能实现

8.2.1 百万级UV统计的实现策略——HyperLogLog

什么是UV统计

UV:全称Unique Visitor,也叫独立访客量,是指通过互联网访问、浏览这个网页的自然人。1天内同一个用户多次访问该网站,只记录1次。

什么是PV统计
PV:全称Page View,也叫页面访问量或点击量,用户每访问网站的一个页面,记录1次PV,用户多次打开页面,则记录多次PV。往往用来衡量网站的流量
 

传统方式实现UV统计面对的难题

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

高效的解决措施——使用HyperLogLog

        Hyperloglog(HLL)是从Loglog算法派生的概率算法,用于确定非常大的集合的基数,而不需要存储其所有值。

        Redis中的HLL是基于string结构实现的,单个HLL的内存永远小于16kb,内存占用低的令人发指!作为代价,其测量结果是概率性的,有小于0.81%的误差。不过对于UV统计来说,这完全可以忽略。

HyperLogLog的原理

哈希处理
        对每个要加入的元素进行哈希处理。这一步骤将元素映射为一个固定长度的二进制串。


划分与索引——分桶
        在 Redis 的实现中,使用 64bit 的 Hash 函数,其中 14bit 用于桶索引(将原始集合分成多个子集),剩下的 50bit 用于计算前导零的个数。这意味着 Redis 中的 HyperLogLog 使用16384个桶,每个桶可以表达的最大数字是:2^5+2^4+...+1 = 63 


估计基数——桶估计值公式
        通过使用补偿和线性计数的技术,将最大前导零位转换为基数估计值。具体的计算方法可以使用查表或其他数学模型来实现。在 Redis 的 HyperLogLog 实现中,有一个基于经验值的参数 alpha_m 用于调整估计值,以确保在大多数情况下都能提供较为准确的估计。


误差修正——偏差修正因子
由于 HyperLogLog 是一种概率性算法,其估计结果会存在一定的误差。Redis 通过应用修正公式来纠正这些估计误差,从而提供更加准确的基数估计。

合并与查询
        
HyperLogLog 支持多个数据集的并集操作,可以将多个 Key 的 UV 进行去重合并,且合并的复杂度是 O(1)。同时,获取一个或多个 HyperLogLog 结构的基数估计值也非常高效,查询的复杂度同样是 O(1)。
 

更多请看:HyperLogLog 算法的原理讲解以及 Redis 是如何应用它的聪明的你可能会马上想到,用 HashMap 这种数 - 掘金 (juejin.cn)

8.2.2 使用HyperLogLog实现百万级UV统计测试

我们向Redis插入100万条数据,用来模拟超大UV访问量的统计,并计算使用HyperLogLog存储需要消耗的内存大小以及统计误差,从而向大家展示Hyper在统计方面的优秀性能

/*** 向Hyperloglog插入100万条数据进行测试,查看内存占用情况*/@Testvoid testHyperLogLog() {// 开始循环for(int i=0;i<1000;i++){String[] values = new String[1000];for(int j=0;j<1000;j++){values[j] = "user_" + i + "_" + j;}stringRedisTemplate.opsForHyperLogLog().add("hl2",values);}// 统计数量Long count = stringRedisTemplate.opsForHyperLogLog().size("hl2");System.out.println("count = " + count);}

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

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

相关文章

CST软件超表面---电容或变容二极管调焦反射镜

可变焦的超表面&#xff08;focus tunable metasurface&#xff09;类型反射镜具有超薄、智能可控等特点&#xff0c;可用于成像、显微等应用。而且经常有朋友问如何用电容或二极管调控超材料&#xff0c;这期我们就用个简单的案例看看调控效果。 1. 单元仿真 单元尺寸我们用1…

【原创教程】电气电工20:一文弄透电气电工辅材

电气电工这些知识点,我们描述的比较细,虽然看起来比较简单,但是它是后面我们技能提升的基础,如果我们后面学电气工程师相关知识,这些都属于基本功。 接着我们来看一下电气辅材。 电气辅材定义: 电气辅材是指与电气设备固有的元器件配套使用的配件和器具。常见的电气辅…

Python “函数” ——Python面试100道实战题目练习,巩固知识、检查技术、成功就业

本文主要是作为Python中函数的一些题目&#xff0c;方便学习完Python的函数之后进行一些知识检验&#xff0c;感兴趣的小伙伴可以试一试&#xff0c;含选择题、判断题、实战题、填空题&#xff0c;答案在第五章。 在做题之前可以先学习或者温习一下Python的函数&#xff0c;推荐…

构建高效用户中心的技术方案

一、架构设计 在设计用户中心时&#xff0c;首先要考虑其架构。推荐采用微服务架构&#xff0c;这样可以将不同功能模块独立开来&#xff0c;便于后期维护和扩展。例如&#xff0c;可以将用户注册、登录、信息管理、权限控制等功能分为不同的服务模块。 二、前端开发 前端是…

【2022工业图像异常检测文献】PatchCore

Towards Total Recall in Industrial Anomaly Detection 1、Background 工业图像异常检测主要解决 冷启动问题 &#xff0c;即仅使用正常&#xff08;无缺陷&#xff09;样本图像来训练模型。 现有的关于冷启动工业视觉异常检测的工作依赖于通过自编码方法、生成对抗网络或其…

高速CT滑环的特点分析

高速CT滑环在现代成像技术中发挥着至关重要的作用&#xff0c;尤其是在医学成像设备和工业检测系统中。这种滑环不仅满足高速旋转的需求&#xff0c;还确保了信号和电力的稳定传输。本文将详细分析高速CT滑环的主要特点及其应用优势。 高速CT滑环的第一个特点是其高传输速率。…

101. 对称二叉树【同时遍历两棵树】【C++】

题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 提示&#xff1a; …

Flet内置图标库ft.icons的图标如何使用庖丁解牛深度解读讲解,源代码IDE运行和调试通过

序言 Flet内置图标库图标丰富多彩、包罗万象。flet内置图标库指ft.icons图标库。使用Flet框架编写程序和项目&#xff0c;就要使用 Flet 内置图标库图标。使用 Flet 内置图标库的图标好处很多。 具体说有以下好处&#xff1a; 便捷性&#xff1a;无需额外寻找和下载图标资源&…

「OC」present和push操作区别以及混合推出的实现

「OC」present和push操作区别以及混合推出的实现 文章目录 「OC」present和push操作区别以及混合推出的实现前言present用途while循环越级返回通知越级返回添加present动画 push模态视图和push视图混合跳转操作一&#xff1a;控制器Apresent控制器B&#xff0c;控制器B再将控制…

影视会员充值api?接口对接需要做哪些准备工作?

影视会员充值 API 接口对接主要有以下步骤&#xff1a; 1.前期准备 明确自身需求&#xff1a;确定你希望通过 API 接口实现的功能&#xff0c;例如支持哪些影视平台的会员充值、是否需要获取会员信息、是否需要订单查询功能等。选择合适的 API 提供商&#xff1a;官方视频平台…

中国电子学会202312青少年软件编程(Python)等级考试试卷(三级)真题

2023年12月青少年软件编程Python等级考试(三级)真题试卷 题目总数:38 总分数:100 一、选择题 第 1 题 单选题 一个非零的二进制正整数,在其末尾添加两个“0”,则该新数将是原数的?( ) A.10倍 B.2倍 C.4倍 D.8倍 第 2 题 单选题 2023年亚运会将在杭…

分步指南:如何使用 ChatGPT 撰写文献综述

撰写文献综述对于研究人员和学生来说,往往是一项既耗时又复杂的任务。这一过程不仅要求对所选主题的现有研究进行全面的了解和掌握,还需要学术严谨性。然而,随着像 ChatGPT 这样的高级语言模型的广泛应用,撰写文献综述的过程变得更加高效和简化。通过合理利用 ChatGPT,研究…

跨国公司决策的影响与中国IT产业的应对

跨国公司在华研发中心的调整是一个复杂的现象&#xff0c;它可能受到多种因素的影响&#xff0c;包括全球经济环境的变化、成本考量、战略重心的转移以及地缘政治因素等。IBM中国研发中心的撤出可能会对中国IT行业造成短期的就业压力&#xff0c;加速人才流动&#xff0c;并促使…

【LeetCode】每日一题 2024_9_20 统计特殊整数(数位 DP)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;统计特殊整数 代码与解题思路 func countSpecialNumbers(n int) int { // 今天的题目是数位 DP&#xff0c;我不会做&#xff0c;所以现场学习了一下灵神的数位 DP 模版s : strconv.Itoa…

轻松打造:用Python实现手机与电脑间的简易消息系统

展示&#x1f3a5; 观看视频&#xff1a;&#x1f440;&#xff0c;这是之前完成的一个项目&#xff0c;但今天我们的重点不是这个哦。 告别往昔&#xff0c;启航新篇章 现象&#x1f31f; 智能互动&#xff1a;&#x1f4f1; 我们每天都在享受与智能设备的互动&#xff0c;…

哪个快?用300万个图斑测试ArcGIS Pro的成对叠加与经典叠加

​​​ 点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 点击学习——>遥感影像综合处理4大遥感软件ArcGISENVIErdaseCognition 在使用ArcGIS Pro的过程中&#xff0c;很多朋友发现&#xff0c;Pro有个成对叠加工具集。很多…

图片转pdf在线怎么转?分享5种简单好用的转换方法

在日常工作和学习中&#xff0c;我们经常会遇到需要将图片转换为PDF格式的情况。无论是为了保存文档方便查阅&#xff0c;还是为了提升文件的专业性和安全性&#xff0c;掌握图片转PDF的技巧都显得尤为重要。下面给大家分享5种转换方法&#xff0c;简单高效&#xff0c;一起来了…

b2b2c商城系统好用么 多用户商城系统四大盈利模式

商淘云B2B2C商城系统能帮助企业快速搭建企业自己的多用户商城系统&#xff0c;它提供了多种功能&#xff0c;如多商家管理、订单处理、支付模块集成等&#xff0c;适合各种规模的企业。用户界面友好&#xff0c;且支持定制化&#xff0c;能满足不同业务需求。 多用户商城有四大…

HTTP协议详解以及常见的状态码

HTTP协议的定义&#xff1a; HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是一种建立在TCP&#xff08;传输控制协议&#xff09;之上的无状态连接协议。它是互联网的基础协议之一&#xff0c;用于客户端与服务器之间的通信。HTTP规定…

【C++二叉树】105.从前序与中序遍历序列构造二叉树

105. 从前序与中序遍历序列构造二叉树 - 力扣&#xff08;LeetCode&#xff09; 根据前序遍历和中序遍历构建二叉树 前序遍历访问方式&#xff1a;根-左子树-右子树 中序遍历访问方式&#xff1a;左子树-根-右子树 思路分析&#xff1a; 前序中序可以构建一颗二叉树&#xf…