【Redis】签到点赞和UV统计

Redis签到点赞和UV统计

点赞

点赞功能分析

需求:

  1. 同一个用户只能点赞一次,再次点击则取消点赞
  2. 如果当前用户已经点赞,则点赞按钮高亮显示(前端判断字段isLike属性)

实现步骤:

  1. 利用Redis的set集合判断是否点赞过,将用户id保存到set中
  2. 判断当前登录用户是否点赞过,赋值给isLike字段
  3. 通过Redis的set集合中Scard命令获取成员个数,即点赞次数

业务实现

LikedDTO

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LikedDTO {/*** 点赞数量*/long likedSum;/*** 用户是否点过赞*/Boolean isLiked;
}

点赞操作

// 点赞操作
@Override
public String doLike() {String key = "RedisSessionDemo:liked";String phone = UserHolder.getUser().getPhone();// 查询是否点赞过Boolean isLiked = redisTemplate.opsForSet().isMember(key, phone);if (BooleanUtil.isTrue(isLiked)) {// 点赞过 -> 取消点赞redisTemplate.opsForSet().remove(key, phone);return "取消点赞成功";}// 没点赞过 -> 点赞redisTemplate.opsForSet().add(key, phone);return "点赞成功";
}

获取点赞数据

// 获取点赞数据
@Override
public LikedDTO getLiked() {String key = "RedisSessionDemo:liked";Long likedNum = redisTemplate.opsForSet().size(key);if (likedNum == null) {likedNum = 0L;}UserDTO user = UserHolder.getUser();Boolean isLiked = false;if (user != null) {isLiked = redisTemplate.opsForSet().isMember(key, user.getPhone());}return new LikedDTO(likedNum, isLiked);
}

点赞排行

功能分析

点赞排行:类似朋友圈的点赞列表,按照点赞的先后顺序展示头像等信息。

使用 sorted set 结构,将点赞的时间戳作为分数值记录。

功能实现

修改点赞函数

// 获取点赞数据
@Override
public LikedDTO getLiked2() {String key = "RedisSessionDemo:liked";Long likedNum = redisTemplate.opsForZSet().size(key);if (likedNum == null) {likedNum = 0L;}UserDTO user = UserHolder.getUser();boolean isLiked = false;if (user != null) {Double score = redisTemplate.opsForZSet().score(key, user.getPhone());isLiked = (score != null && score > 0);}return new LikedDTO(likedNum, isLiked);
}// 点赞操作
@Override
public String doLike2() {String key = "RedisSessionDemo:liked";String phone = UserHolder.getUser().getPhone();// 查询是否点赞过Double isLiked = redisTemplate.opsForZSet().score(key, phone);if (isLiked != null && isLiked > 0) {// 点赞过 -> 取消点赞redisTemplate.opsForZSet().remove(key, phone);return "取消点赞成功";}// 没点赞过 -> 点赞redisTemplate.opsForZSet().add(key, phone, System.currentTimeMillis());return "点赞成功";
}

获取点赞列表

// 获取点赞列表
@Override
public List<String> getLikedList() {String key = "RedisSessionDemo:liked";// 获取所有元素Set<String> set = redisTemplate.opsForZSet().range(key, 0, -1);if (set != null) {return new ArrayList<>(set);}return Collections.emptyList();
}

用户签到

BitMap用法

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

把每一个bit位对应当月的每一天,形成了映射关系。用0和1标示业务状态,这种思路就称为位图(BitMap)。

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

BitMap的操作命令有:

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

实现签到功能

因为BitMap底层是基于String数据结构,因此其操作也都封装在字符串相关操作中了。

public Boolean sign() {String phone = UserHolder.getUser().getPhone();Date date = new Date();String yearAndMonth = new SimpleDateFormat("yyyy:MM").format(date);String key = "RedisSessionDemo:user:sign:" + phone + ":" + yearAndMonth;int day = Integer.parseInt(new SimpleDateFormat("DD").format(date));// 实现签到redisTemplate.opsForValue().setBit(key, day, true);return true;
}

签到统计

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

封装SignData类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SignData {// 月签到次数Integer MonthTimes;// 月连续签到次数Integer ContinuousTimes;
}

业务实现

@Override
public SignData signdata() {// 获取 bitmapString phone = UserHolder.getUser().getPhone();Date date = new Date();String yearAndMonth = new SimpleDateFormat("yyyy:MM").format(date);String key = "RedisSessionDemo:user:sign:" + phone + ":" + yearAndMonth;int day = Integer.parseInt(new SimpleDateFormat("DD").format(date));List<Long> list = redisTemplate.opsForValue().bitField(key, BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(day + 1)).valueAt(0));if (list == null || list.isEmpty()) {return new SignData(0, 0);}Long sign = list.get(0);if (sign == null) {return new SignData(0, 0);}// 统计计算int MonthTimes = 0;int ContinuousTimes = 0;boolean isContinuous = true;while (sign != 0) {// 连续签到if (isContinuous) {if ((sign & 1) == 1) {ContinuousTimes++;} else {isContinuous = false;}}// 月签到次数if ((sign & 1) == 1) {MonthTimes++;}sign = sign >> 1;}return new SignData(MonthTimes, ContinuousTimes);
}

UV统计

HyperLogLog

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

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

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

Redis中的HLL是基于string结构实现的,单个HLL的内存永远小于16kb,内存占用低的令人发指!

作为代价,其测量结果是概率性的,有小于0.81%的误差。不过对于UV统计来说,这完全可以忽略。

  1. 作用:做海量数据的统计工作
  2. 优点:内存占用极低、性能非常好
  3. 缺点:有一定的误差

业务实现

@Test
void hyperlogTest() {for (int i = 0; i < 100; i++) {stringRedisTemplate.opsForHyperLogLog().add("hyperlogTest", "user-" + i);}Long size = stringRedisTemplate.opsForHyperLogLog().size("hyperlogTest");System.out.println(size);
}

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

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

相关文章

五款颠覆工作方式的工作软件

在当今快节奏的工作环境中&#xff0c;选择合适的工作软件是提高效率、实现协作的关键。感谢你的提问&#xff0c;下面我将为你介绍五款令人赞叹的工作软件&#xff0c;它们会让你的工作变得更有趣而富有成效&#xff01; 1. 亿可达 是我最近在用的一款软件连接器&#xff0c…

ubuntu16.04环境轻松安装和应用opencv4.9.0(基于源码编译)

目录 一、环境准备 1、安装cmake 2、安装依赖 3、从github上下载opencv4.9.0.zip 二、安装opencv4.9.0 1、解压4.9.0.zip 2、进入build目录编译 3、安装编译好的相关库 4、修改opencv配置文件并使其生效 5、添加PKG_CONFIG路径&#xff0c;并使其生效 三、opencv环境…

聚道云软件连接器:连接薪人薪事与携程商旅的桥梁,出差管理效率的新篇章

客户介绍 某科技有限公司是一家专注于提供数字化解决方案的高科技企业。公司拥有一支由业内资深专家和优秀工程师组成的团队&#xff0c;致力于为企业提供全方位的数字化服务。该公司拥有自主研发能力&#xff0c;拥有多项知识产权和专利技术&#xff0c;确保为客户提供技术领…

Aigtek大功率信号源怎么使用的

大功率信号源是在实验室、测试和通信系统中经常使用的重要设备。它能够提供高功率的信号&#xff0c;用于驱动各种设备和系统。在使用大功率信号源时&#xff0c;有一些关键的步骤和指南&#xff0c;可以确保安全、有效地操作设备并获得稳定的输出。本文将详细介绍大功率信号源…

DevOps落地笔记-05|非功能需求:如何有效关注非功能需求

上一讲主要介绍了看板方法以及如何使用看板方法来解决软件研发过程中出现的团队过载、工作不均、任务延期等问题。通过学习前面几个课时介绍的知识&#xff0c;你的团队开始源源不断地交付用户价值。用户对交付的功能非常满意&#xff0c;但等到系统上线后经常出现服务不可用的…

C#使用OpenCvSharp4库中5个基础函数-灰度化、高斯模糊、Canny边缘检测、膨胀、腐蚀

C#使用OpenCvSharp4库中5个基础函数-灰度化、高斯模糊、Canny边缘检测、膨胀、腐蚀 使用OpenCV可以对彩色原始图像进行基本的处理&#xff0c;涉及到5个常用的处理&#xff1a; 灰度化 模糊处理 Canny边缘检测 膨胀 腐蚀 1、测试图像lena.jpg 本例中我们采用数字图像处…

Java玩转《啊哈算法》解密QQ号之队列

行有不得&#xff0c;反求诸己 文章目录 开头代码地址引子案例分析代码 队列封装升级演示 开头 各位好&#xff01;本人在看《啊哈算法》&#xff0c;写的确实不错。 但略微遗憾的是&#xff0c;书籍示例代码是c语言&#xff0c;不是本人常用的Java。 那就弥补遗憾&#xff…

分布式搜索引擎_学习笔记_3

分布式搜索引擎03 0.学习目标 1.数据聚合 **聚合&#xff08;aggregations&#xff09;**可以让我们极其方便的实现对数据的统计、分析、运算。例如&#xff1a; 什么品牌的手机最受欢迎&#xff1f;这些手机的平均价格、最高价格、最低价格&#xff1f;这些手机每月的销售…

matlab中的图窗属性和坐标轴的属性

图窗的Position和Outerposition Position 指定窗口的尺寸和窗口在屏幕中的位置。 Outerposition 指定窗口外轮廓的大小和位置。 两者都是用一个4维向量来定义&#xff0c;格式为[左 底 宽 高]。 可通过set函数修改Position和Outerposition&#xff0c;如下&#xff1a;在屏幕左…

color - 让你的输出带点颜色

color color 是一个可以让你输出带颜色文本的库。 安装 go get github.com/fatih/color示例 输出到控制台 // 这会直接输出到控制台 color.Cyan("Prints text in cyan.")// 每个调用末尾会自动加上换行 color.Blue("Prints %s in blue.", "text&…

VMware vCenter告警:vSphere UI运行状况警报

vSphere UI运行状况警报 不会详细显示告警的具体内容&#xff0c;需要我们自己进一步确认告警原因。 vSphere UI运行状况警报是一种监控工具&#xff0c;用于检测vSphere环境中的潜在问题。当警报触发时&#xff0c;通常表示系统遇到了影响性能或可用性的问题。解决vSphere UI…

软件测试之软件缺陷管理

什么是软件缺陷 标准的定义&#xff1a;从产品内部看&#xff0c;缺陷是软件产品开发或维护过程中存在的错误、毛病等各种问题&#xff1b;从产品外部看&#xff0c;缺陷是系统所需要实现的某种功能的失效或违背 软件缺陷的生命周期 一个缺陷的正常生命周期是 新建&#xff…

如何分辨坏信息?

每当有社会热点&#xff0c;大家也许都会遇到一个困扰&#xff1a; 铺天盖地的信息&#xff0c;实在是太多了。究竟哪一些值得信任&#xff0c;哪些不值得信任&#xff1f;哪些可以接受&#xff0c;哪些最好保持怀疑&#xff1f; 我想用这篇文章&#xff0c;彻底把这个问题讲清…

CSS定位

定位的组成&#xff1a; 这个属性只有当position属性设置为absolute、fixed、relative时才有效。而且在position属性取值不同时&#xff0c;它们的含义也不同。left和right属性值除了可以设置为绝对的像素数外&#xff0c;还可以设置百分数。 定位模式&#xff1a; 静态定位st…

易语言系列学习1

通过本文章你会学习到 如果 如果真 获取编辑框内容 关闭本程序 监听按键让它等价于点击某个按钮 运算&#xff1a;或 且 非&#xff08;注意中间要有一个空格&#xff0c;否则会报错&#xff09; 效果 .版本 2.程序集 窗口程序集_启动窗口.子程序 _按钮2_被单击. 如果真 (编…

【项目实践02】【优先级阻塞队列】

文章目录 一、前言二、项目背景三、实现方案四、思路延伸1. 优先级队列1.1 concurrent 包下的 PriorityBlockingQueue1.2 Redisson 的优先级阻塞队列 2. jvisualvm 远程连接3. Jstack 高 CPU 排查 五、参考内容 一、前言 本系列用来记录一些在实际项目中的小东西&#xff0c;并…

qemu 抓取linux kernel vmcore

一、背景 在qemu调试linux kernel时 有时我们会遇到dump 情况&#xff0c;这时可以通过gdb 方式连接分析dump&#xff0c; 但实际中我们用得更多的是离线dump 分析&#xff0c;分析的文件通常是vmcore&#xff08;linux kernel panic 生成的coredump文件&#xff09;或者ramdu…

【多个SpringBoot模块项目如何变成聚合项目】

【前言】 项目虽然是Eureka、OpenFeign 进行服务注册和服务调用&#xff0c;但是每个模块都是一个单独的SpringBoot&#xff0c;启动每个模块都需要单独启动一个idea,觉得这个过于繁琐&#xff0c;现在想把项目变成一个聚合项目&#xff0c;只需要启动一个idea即可。 【过程】…

【数据结构 08】红黑树

一、概述 红黑树&#xff0c;是一种二叉搜索树&#xff0c;每一个节点上有一个存储位表示节点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个节点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长上两倍&#xff0c;因而是接进…

UGUI中Text和TextMeshPro实现图文混排方式

一些项目中实现图文混排是自定义一个脚本去继承Text类&#xff0c;然后文本中用富文本的方式进行图片和超链接的定义&#xff0c;在代码中用正则表达式匹配的方式把文本中图片和超链接给替换&#xff0c;如下&#xff1a; TextMeshPro实现是生成SpriteAsset进行图文混排的&…