当前位置: 首页 > news >正文

使用Redis统计网站的UV/DAU

HyperLogLog/BitMap

统计UV、DAU需要用到Redis的高级数据类型

M

public class RedisKeyUtil {private static final String PREFIX_UV = "uv";private static final String PREFIX_DAU = "dau";// a single day's UVpublic static String getUVKey(String date){return PREFIX_UV + SPLIT + date;}// a series of days' UVpublic static String getUVKey(String startDate, String endDate){return PREFIX_UV + SPLIT + startDate + SPLIT + endDate;}// get the DAU of a single daypublic static String getDAUKey(String date){return PREFIX_DAU + SPLIT + date;}// get the DAU of a series of dayspublic static String getDAUKey(String startDate, String endDate){return PREFIX_DAU + SPLIT + startDate + SPLIT + endDate;}
}

C

@Service
public class DataService {@Autowiredprivate RedisTemplate redisTemplate;private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");// add the specified IP address to the UVpublic void recordUV(String ip){String redisKey = RedisKeyUtil.getUVKey(dateFormat.format(new Date()));redisTemplate.opsForHyperLogLog().add(redisKey, ip);}// query the specified range of days' UVpublic long calculateUV(Date start, Date end) {if(start == null || end == null){throw new IllegalArgumentException("start and end must not be null");}if(start.after(end)){throw new IllegalArgumentException("start date should be before end date");}// get all the keys of those daysList<String> keyList = new ArrayList<>();Calendar calendar = Calendar.getInstance();calendar.setTime(start);while(!calendar.getTime().after(end)){String redisKey = RedisKeyUtil.getUVKey(dateFormat.format(calendar.getTime()));keyList.add(redisKey);// add calendar to 1calendar.add(Calendar.DATE, 1);}// merge all the UV of those daysString redisKey = RedisKeyUtil.getUVKey(dateFormat.format(start), dateFormat.format(end));redisTemplate.opsForHyperLogLog().union(redisKey, keyList.toArray());// return the statistics resultreturn redisTemplate.opsForHyperLogLog().size(redisKey);}// add the specified user to the DAUpublic void recordDAU(int userId){String redisKey = RedisKeyUtil.getDAUKey(dateFormat.format(new Date()));redisTemplate.opsForValue().setBit(redisKey, userId, true);}// query the specified range of days' DAVpublic long calculateDAU(Date start, Date end){if(start == null || end == null){throw new IllegalArgumentException("start and end must not be null");}if(start.after(end)){throw new IllegalArgumentException("start date should be before end date");}// get all the keys of those daysList<byte[]> keyList = new ArrayList<>();Calendar calendar = Calendar.getInstance();calendar.setTime(start);while(!calendar.getTime().after(end)){String key = RedisKeyUtil.getDAUKey(dateFormat.format(calendar.getTime()));keyList.add(key.getBytes());// add calendar to 1calendar.add(Calendar.DATE, 1);}// or operationreturn (long) redisTemplate.execute(new RedisCallback() {@Overridepublic Object doInRedis(RedisConnection connection) throws DataAccessException {String redisKey = RedisKeyUtil.getDAUKey(dateFormat.format(start), dateFormat.format(end));connection.stringCommands().bitOp(RedisStringCommands.BitOperation.OR,redisKey.getBytes(), keyList.toArray(new byte[0][0]));return connection.stringCommands().bitCount(redisKey.getBytes());}});}
}

使用拦截器记录访问

@Component
public class DataInterceptor implements HandlerInterceptor{@Autowiredprivate DataService dataService;@Autowiredprivate HostHolder hostHolder;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// record into the UVString ip = request.getRemoteHost();dataService.recordUV(ip);// record into the DAUUser user = hostHolder.getUser();if(user != null){dataService.recordDAU(user.getId());}return true;}
}

配置拦截器

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate DataInterceptor dataInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(dataInterceptor).excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg");}
}

V

@Controller
public class DataController {@Autowiredprivate DataService dataService;// the page of the statistics@RequestMapping(path = "/data", method = {RequestMethod.GET, RequestMethod.POST})public String getDataPage() {return "/site/admin/data";}// calculates the UV of the site
//    @PostMapping(path = "/data/uv")@RequestMapping(path = "/data/uv", method = {RequestMethod.GET/*, RequestMethod.POST*/})public String getUV(@DateTimeFormat(pattern = "yyyy-MM-dd") Date start,@DateTimeFormat(pattern = "yyyy-MM-dd") Date end, Model model) {long uv = dataService.calculateUV(start, end);model.addAttribute("uvResult", uv);model.addAttribute("uvStartDate", start);model.addAttribute("uvEndDate", end);// `forward` means this function just disposal a half of the request,// and the rest of request need to be executed by other functions// post request still be post after forwardingreturn "forward:/data";}// calculates the DAU of the site
//    @PostMapping(path = "/data/dau")@RequestMapping(path = "/data/dau", method = {RequestMethod.GET/*, RequestMethod.POST*/})public String getDAU(@DateTimeFormat(pattern = "yyyy-MM-dd") Date start,@DateTimeFormat(pattern = "yyyy-MM-dd") Date end, Model model) {long dau = dataService.calculateDAU(start, end);model.addAttribute("dauResult", dau);model.addAttribute("dauStartDate", start);model.addAttribute("dauEndDate", end);// `forward` means this function just disposal a half of the request,// and the rest of request need to be executed by other functions// post request still be post after forwardingreturn "forward:/data";}
}

相关文章:

使用Redis统计网站的UV/DAU

HyperLogLog/BitMap 统计UV、DAU需要用到Redis的高级数据类型 M public class RedisKeyUtil {private static final String PREFIX_UV "uv";private static final String PREFIX_DAU "dau";// a single days UVpublic static String getUVKey(String …...

【python】报错:ImportError: DLL load failed: 找不到指定的模块 的详细解决办法

原因&#xff1a;安装的包与python版本不一致 解决方法&#xff1a; 查看python版本&#xff1a; #python / #python -V Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] on win32只查看python第三方模块&#xff08;库、包&…...

SemrushBot蜘蛛爬虫屏蔽方式

查看访问日志时候发现有SemrushBot爬虫 屏蔽方法&#xff1a; 使用robots.txt文件是一种标准的协议,用于告诉搜索引擎哪些页面可以和不能被爬取,如想禁止Googlebot爬取整个网站的话,可以在该文件中添加以下内容: User-agent: Googlebot Disallow: / 对于遵循robots协议的蜘蛛…...

6 ssh面密登录

1. 首先进入自己的家目录&#xff0c;执行命令 [atguiguhadoop102 .ssh]$ ssh-keygen -t rsa然后敲&#xff08;三个回车&#xff09;&#xff0c;就会生成两个文件id_rsa&#xff08;私钥&#xff09;、id_rsa.pub&#xff08;公钥&#xff09; 2. 将公钥拷贝到要免密登录的…...

基于微信小程序的汽车租赁系统的设计与实现ljx7y

汽车租赁系统&#xff0c;主要包括管理员、用户二个权限角色&#xff0c;对于用户角色不同&#xff0c;所使用的功能模块相应不同。本文从管理员、用户的功能要求出发&#xff0c;汽车租赁系统系统中的功能模块主要是实现管理员后端&#xff1b;首页、个人中心、汽车品牌管理、…...

优化学习体验的在线考试系统

随着互联网的发展&#xff0c;在线教育逐渐成为学习的主要方式之一。在线考试系统作为在线教育的重要组成部分&#xff0c;对于学习者提供了更为便捷和灵活的学习方式。但是&#xff0c;如何优化学习体验&#xff0c;提高学习效果&#xff0c;仍然是在线考试系统需要解决的问题…...

1267. 统计参与通信的服务器

题目描述&#xff1a; 这里有一幅服务器分布图&#xff0c;服务器的位置标识在 m * n 的整数矩阵网格 grid 中&#xff0c;1 表示单元格上有服务器&#xff0c;0 表示没有。 如果两台服务器位于同一行或者同一列&#xff0c;我们就认为它们之间可以进行通信。 请你统计并返回能…...

【考研数学】矩阵、向量与线性方程组解的关系梳理与讨论

文章目录 引言一、回顾二、梳理齐次线性方程组非齐次线性方程组 写在最后 引言 两个原因让我想写这篇文章&#xff0c;一是做矩阵题目的时候就发现这三货经常绑在一起&#xff0c;让人想去探寻其中奥秘&#xff1b;另一就是今天学了向量组的秩&#xff0c;让我想起来了之前遗留…...

打造个人的NAS云存储-通过Nextcloud搭建私有云盘实现公网远程访问

文章目录 摘要1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 摘要 Nextcloud,它是ownCloud的一个分支,是一个文件共享服…...

FFI绕过disable_functions

文章目录 FFI绕过disable_functions[RCTF 2019]NextphpPHP7.4 FFI参考 FFI绕过disable_functions [RCTF 2019]Nextphp 首先来看这道题目 index.php <?php if (isset($_GET[a])) {eval($_GET[a]); } else {show_source(__FILE__); }查看一下phpinfo 发现过滤了很多函数&…...

53 个 CSS 特效 2

53 个 CSS 特效 2 这里是第 17 到 32 个&#xff0c;跟上一部分比起来多了两个稍微大一点的首页布局&#xff0c;上篇&#xff1a;53 个 CSS 特效 1&#xff0c;依旧&#xff0c;预览地址在 http://www.goldenaarcher.com/html-css-js-proj/&#xff0c;git 地址&#xff1a; …...

ubuntu学习(六)----文件编程实现cp指令

1 思路 Linux要想复制一份文件通常指令为&#xff1a; cp src.c des.c 其中src.c为源文件&#xff0c;des.c为目标文件。 要想通过文件编程实现cp效果&#xff0c;思路如下 1 首先打开源文件 src.c 2 读src到buf 3 创建des.c 4 将buf写入到des.c 5 close两个文件 2 实现 vi …...

wireshark过滤器的使用

目录 wiresharkwireshark的基本使用wireshark过滤器的区别 抓包案例 wireshark wireshark的基本使用 抓包采用 wireshark&#xff0c;提取特征时&#xff0c;要对 session 进行过滤&#xff0c;找到关键的stream&#xff0c;这里总结了 wireshark 过滤的基本语法&#xff0c;…...

Zookeeper 脑裂问题

什么是脑裂&#xff1f; 脑裂(split-brain)就是“大脑分裂”&#xff0c;也就是本来一个“大脑”被拆分了两个或多个“大脑”&#xff0c;如果一个人有多个大脑&#xff0c;并且相互独立的话&#xff0c;那么会导致人体“手舞足蹈”&#xff0c;“不听使唤”。 脑裂通常会出现…...

计算机网络高频面试题解(一)

1. OSI七层模型 2. TCP/IP五层模型 3. TCP、UDP区别 4. TCP三次握手 5. TCP四次挥手 6. TCP状态转换图 7.TCP状态中TIME_WAIT作用 8. TCP连接建立为什么不是两次握手 9. TCP第三次握手失败会出现什么 10. TCP长连接和短链接及优缺点...

从0-1的docker镜像服务构建

文章目录 摘要一、环境准备1、docker安装2、docker-compose安装 二、镜像制作2.1、编写Dockerfile文件2.1.1、熟悉常用Dockerfile命令2.1.2、制作php镜像案例 2.2、build镜像 三、docker-compose管理容器3.1、编写docker-compose.ymal配置文件3.2、编写systemctl配置 摘要 由于…...

RabbitMQ、Kafka、RocketMQ:特点和适用场景对比

推荐阅读 AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 资源分享 史上最全文档AI绘画stablediffusion资料分享 AI绘画关于SD,MJ,GPT,SDXL百科全书 「java、python面试题」…...

【实战】十一、看板页面及任务组页面开发(四) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二十六)

文章目录 一、项目起航&#xff1a;项目初始化与配置二、React 与 Hook 应用&#xff1a;实现项目列表三、TS 应用&#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…...

解决docker无法执行定时任务问题

背景 在docker里面想创建定时任务&#xff0c;但是发现时间到了并没有执行&#xff0c;第一时间想到应该是没有开启crond服务&#xff0c;然后执行systemctl status crond.service报错如下所示&#xff1a; System has not been booted with systemd as init system (PID 1).…...

【FreeRTOS】【STM32】中断详细介绍

文章目录 一、三种优先级的概念辨析1. 先理清楚两个概念&#xff1a;CPU 和 MPU2. Cortex-M3 内核与 STM32F1XX 控制器有什么关系3. 优先级的概念辨析① Cortex-M3 内核和 STM32F1XX 的中断优先级② FreeRTOS 的任务的优先级 二、 Cortex-M3 内核的中断优先级1. 中断编号2. 优先…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...