SpringBoot+Redis BitMap 实现签到与统计功能

最近项目里需要集成签到和统计功能,连续签到后会给用户发放一些优惠券和奖品,以此来吸引用户持续在该品台进行活跃。下面我们一些来聊一聊目前主流的实现方案。

因为签到和统计的功能涉及的数据量比较大,所以在如此大的数据下利用传统的关系型数据库进行计算和统计是非常耗费性能的,所以目前市面上主要依赖于高性能缓存RedisBitMap功能来实现。

先看看利用Mysql实现以上功能会有哪些缺陷和短板。

1.使用Mysql实现签到功能

首先我们需要一个签到表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oyI6Br1I-1693143208246)(1.png)]

DROP TABLE IF EXISTS `tb_sign`;
CREATE TABLE `tb_sign` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`user_id` int(11) NOT NULL COMMENT '用户Id',`year` year(4) NOT NULL COMMENT '签到的年',`month` tinyint(2) NOT NULL COMMENT '签到的月',`date` date NOT NULL COMMENT '签到日期',`is_backup` tinyint(1) NOT NULL COMMENT '是否补签',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

用户一次签到,就是一条记录,假如有1000万用户,平均每人每年签到次数为10次,则这张表一年的数据量为 1亿条

每签到一次需要使用(8 + 8 + 1 + 1 + 3 + 1)共22 字节的内存,一个月则最多需要600多字节

这样的坏处,占用内存太大了,极大的消耗内存空间!

我们可以根据 Redis中 提供的 BitMap 位图功能来实现,每次签到与未签到用0 或1 来标识 ,一次存31个数字,只用了2字节 这样我们就用极小的空间实现了签到功能

2.Redis BitMap

2.1 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出现的位置

2.2 使用 BitMap 完成功能实现

利用SETBIT新增key 进行存储

SETBIT bm1 0 1

看不懂上面的指令?没关系,我们可以通过help指令查看提示

help SETBIT

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-28566Xts-1693143208248)(2.png)]
通过这个指令可以看出Redis SETBIT 命令用于对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。位的设置或清除取决于 value,可以是 0 或者是 1 。

当 key 不存在时,自动生成一个新的字符串值。字符串会进行伸展以确保它可以将 value 保存在指定的偏移量上。当字符串值进行伸展时,空白位置以 0 填充。offset 参数必须大于或等于 0 ,小于 2^32 (bit 被限制在 512 MB 之内)。

提示:如果 offset 偏移量的值较大,计算机进行内存分配时可能会造成 Redis 服务器被阻塞。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QVfbhrcc-1693143208249)(3.png)]
这样的话我们就可以通过偏移量设置每一天的签到情况:

  • 偏移量:表示天
  • val值:表示是否签到
    • 已签到设置为1
    • 未签到设置0

下面我们只需要通过GETBIT命令就可以查看每一天的签到情况

GETBIT bm1 2

表示查看bm1用户第二天的签到情况
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rZN6uEyA-1693143208250)(4.png)]
同样,我们可以通过BITCOUNT可以统计出该用户签到了多少天

BITCOUNT bm1 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fdEvzcNG-1693143208251)(5.png)]
通过BITFIELD以原子方式操作(查询、修改、自增)BitMap中bit数组中的指定位置(offset)的值

明天继续更新

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

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

相关文章

Python|OpenCV-鼠标自动绘制图像(4)

前言 本文是该专栏的第4篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 在本专栏之前,有详细介绍使用OpenCV绘制图形以及添加文字的方法,感兴趣的同学可往前翻阅查看“Python|OpenCV-绘制图形和添加文字的方法(2)”。 而本文重点来介绍使用OpenCV来操作鼠标,以…

tp5使用redis及redis7.2安装到window系统上面

redis安装教程 redis7.2安装到window系统上面 https://download.csdn.net/download/qq_39161501/88269037 解决方案:修改配置php.ini文件 打开Apache目录下的php.ini文件,搜索extension,在空白处加上下列代码: 注:e…

Linux进程概念及其状态

文章目录 🍇1. 什么是进程🍈1.1 概念🍈1.2 理解进程 🍋2. Linux的PCB🍎3. 查看进程 & 杀死进程🍒4. 系统调用获取进程标识符🍓4.1 进程PID🍓4.2 父进程PPID 🍆5. 系统…

[LeetCode] 128. 最长连续序列

题目描述 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入:nums [100,4,200,1,3,2] 输出&…

MVVM架构模式

目录 一、MVVM简介二、MVVM结构三、MVC四、MVP五、MVVM的优势与存在的问题 一、MVVM简介 MVVM是Model-View-ViewModel的简写。即是模型-视图-视图模型。 MVVM架构模式是一种软件设计模式,它将应用程序分为三个部分:模型(Model)、…

说说Flink运行模式

分析&回答 1.开发者模式 在idea中运行Flink程序的方式就是开发模式。 2.local-cluster模式 Flink中的Local-cluster(本地集群)模式,单节点运行,主要用于测试, 学习。 3.Standalone模式 独立集群模式,由Flink自身提供计算资源。 4.Yarn模式 把Fl…

多路波形发生器的控制

本次波形发生器,主要使用运算放大器、NE555以及一些其他的电阻电容器件来实现。整体电路图如下所示: 产生的三角波如下: 正弦波如下 方波如下: 运算放大器(Operational Amplifier,简称OP-AMP)是…

滑动窗口实例5(水果成篮)

题目: 你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按…

【MySQL】实现可扩展性:构建高性能的系统

什么是可扩展性?可扩展性的好处扩展方式纵向扩展(Scaling Up)横向扩展(Scaling Out) 总结 💯感谢 💖 什么是可扩展性? 可扩展性是指系统能够在需要时轻松地适应更多的工作负载和资源…

工厂方法模式:创建对象的灵活与扩展

欢迎来到设计模式系列的第三篇文章!在前两篇文章中,我们已经学习了设计模式的基本概念以及单例模式的应用。 今天,我们将深入探讨第二个模式——工厂方法模式。 工厂方法模式简介 工厂方法模式是一种创建型设计模式,它提供了一…

通讯协议057——全网独有的OPC HDA知识一之接口(十二)IOPCHDA_DataCallback

本文简单介绍OPC HDA规范的IOPCHDA_DataCallback(客户端接口)接口方法,更多通信资源请登录网信智汇(wangxinzhihui.com)。 1)HRESULT OnDataChange(dwTransactionID, hrStatus, dwNumItems, pItemValues, phrErrors) 此方法由客…

jmeter源码二次开发

本文以jmeter5.5为例,扩展“TCP Socket支持定长的返回字节流”功能。 一、 源码本地编译运行 1、在jmeter官网下载源码:jmeter各版本源码地址 2、在idea中用gradle导入jmeter源码,idea中要配置jdk,gradle,我用的是j…

详解mysql事务,事务并发安全问题的复现以及大事务的优化

好文推荐: 2.5万字详解23种设计模式 springboot 实现延时队列(超级实用) 2.5万字讲解DDD领域驱动设计 文章目录 1. 事务定义2. 事务特性(ACID)3. 事务并发问题4. 事务隔离级别5. 基础命令6. 脏读复现7. 不可重复读复现…

【快手小玩法-弹幕游戏】开发者功能测试报告提交模板

背景 快手有明确的要求,准入和准出更加严格,要求有明确的测试报告。格式如下: *本文参考字节wiki:CP侧测试报告模板(复制填写轻雀文档) 其他文章推荐:【抖音小玩法-弹幕游戏】开发者功能测试报告提交模板 一、前言…

Visual Studio编译出来的程序无法在其它电脑上运行

在其它电脑(比如Windows Server 2012)上运行Visual Studio编译出来的应用程序,结果报错:“无法启动此程序,因为计算机中丢失VCRUNTIME140.dll。尝试重新安装该程序以解决此问题。” 解决方法: 属性 -> …

10 mysql tiny/small/medium/big int 的数据存储

前言 这里主要是 由于之前的一个 datetime 存储的时间 导致的问题的衍生出来的探究 探究的主要内容为 int 类类型的存储, 浮点类类型的存储, char 类类型的存储, blob 类类型的存储, enum/json/set/bit 类类型的存储 本文主要 的相关内容是 int 类类型的相关数据的存储 …

变长参数表的用法

变长参数表是一种允许函数接受不定数量和类型的参数的机制&#xff0c;它在C语言中经常用到&#xff0c;比如printf函数。要使用变长参数表&#xff0c;你需要包含<stdarg.h>头文件&#xff0c;它定义了一些宏和类型来处理变长参数。 首先&#xff0c;你需要在函数声明中…

服务器上使用screen的学习记录

服务器上使用screen 训练模型的时候&#xff0c;花费时间是很长的&#xff0c;不可能一直挂在桌面上。所以就想到用screen了。 记录一下简单的操作指令。 创建screen screen -S roof # 新建一个名字为name的窗口&#xff0c;并进入到该窗口中进入后打开环境&#xff0c;运…

RT-Thread 时钟管理

时间是非常重要的概念&#xff0c;和朋友出去游玩需要约定时间&#xff0c;完成任务也需要花费时间&#xff0c;生活离不开时间。操作系统也一样&#xff0c;需要通过时间来规范其任务的执行&#xff0c;操作系统中最小的时间单位是时钟节拍&#xff08;OS Tick&#xff09;。 …

CloudCompare 二次开发(10)——点云投影到平面

目录 一、概述二、代码集成三、结果展示一、概述 不依赖任何第三方点云相关库,使用CloudCompare编程实现点云投影到指定平面,具体计算原理见:PCL 点云投影到拟合平面 二、代码集成 1、mainwindow.h文件public中添加: void doActionProjectToPlane(); // 投影到平面2、…