网站建设协议书范本,专业高端企业网站建设,网络平台制作多少钱,企业wordpress主题下载地址微信公众号访问地址#xff1a;基于Redis的BitMap实现签到、连续签到统计(含源码)
推荐文章#xff1a; 1、springBoot对接kafka,批量、并发、异步获取消息,并动态、批量插入库表; 2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据; 3、基于Redis的Geo实现附…微信公众号访问地址基于Redis的BitMap实现签到、连续签到统计(含源码)
推荐文章 1、springBoot对接kafka,批量、并发、异步获取消息,并动态、批量插入库表; 2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据; 3、基于Redis的Geo实现附近商铺搜索(含源码) 4、基于Redis实现关注、取关、共同关注及消息推送(含源码) 5、SpringBoot整合多数据源并支持动态新增与切换详细教程 6、基于Redis实现点赞及排行榜功能
一、简介
基于Redis的BitMap相关命令实现用户签到、连续签到统计等功能。
1.1、背景 分析使用用一张表来存储用户签到信息假如用户数量庞大平均每人每年签到次数为 10 次则这张表一年的数据量为 1 亿条每签到一次需要使用8 8 1 1 3 1共 22 字节的内存一个月则最多需要 600 多字节。
1.2、BitMap bitmap 不是一个独立的数据类型而是一种特殊的 string 类型它可以将一个 string 类型的值看作是一个由二进制位组成的数组并提供了一系列操作二进制位的命令。一个 bitmap 类型的键最多可以存储 2^32 - 1 个二进制位。 bitmap 类型的底层实现是 SDSsimple dynamic string它和 string 类型相同只是在操作时会将每个字节拆分成 8 个二进制位。 常见用法 Redis中的Bitmap是一种数据结构用于存储和操作位数组bit array。它可以有效地表示指定范围内的位状态每个位的值可以是0或1。使用Bitmap可以进行高效的位级别操作例如对某个位进行设置、获取、翻转等操作以及位的逻辑运算如AND、OR、XOR等。
在Redis中Bitmap的应用场景
1、统计在线用户(签到)可以使用一个Bitmap每个位代表一个用户ID如果某个用户在线则将对应位设置为1否则设置为0。可以通过位操作来统计在线用户的数量。
2、频率统计可以使用一个Bitmap每个位代表一个事件如果事件发生则将对应位设置为1。可以通过位操作来统计某段时间内事件发生的频率。
3、实现布隆过滤器利用 setbit 和 getbit 命令实现快速判断一个元素是否存在于一个集合中。
4、实现位图索引利用 bitop 和 bitpos 命令实现对多个条件进行位运算和定位。
5、统计用户活跃度利用 setbit 和 bitcount 命令实现每天或每月用户登录次数的统计
常用的命令 需要注意的是由于Bitmap是以字节为单位存储的因此对于较大的位图可能会占用较多的内存。在使用Bitmap时需要根据实际情况评估内存消耗。
1.3、BITFIELD使用说明 Redis中的BITFIELD命令是用于对位域bit field进行操作的位域是由多个位组成的数据结构。它允许你对位域进行读取、设置和计算等操作。下面是BITFIELD命令的用法示例
bitfield bitfield_test get u4 0 #从第一个位开始取4个位(0110)结果为无符号数(u)结果6bitfield bitfield_testget u3 2 #从第三个位开始取3个位(101)结果为无符号数(u)结果5bitfield bitfield_testget get i4 0 #从第一个位开始取4个位(0110)结果为有符号数(i)结果6因为结果为有符号数所以第一位符号位为0代表是正数。110为6结果直接为6bitfield bitfield_testget get i3 2 #从第三个位开始取3个位(101)结果为有符号数(i)结果-3取到的结果首位为1代表是负数01需要取补码运算。01取反为10,101为11。11十进制为3因为符号位为1所以最终结果为-3
命令操作案例
redis6.3:0setbit qd_key 0 10redis6.3:0setbit qd_key 1 10redis6.3:0setbit qd_key 2 10redis6.3:0getbit qd_key 101redis6.3:0bitcount qd_key6redis6.3:0bitfield qd_key get u2 01) 3 二、签到功能实现
2.1、需求分析 2.2、代码实现 public Result sign() { // 1.获取当前登录用户// Long userId UserHolder.getUser().getId(); Long userId 999L; // 2.获取日期 使用hutool的日期时间工具-DateUtil Date date DateUtil.date(); // 3.拼接key String keySuffix DateUtil.format(date, :yyyyMM); String key USER_SIGN_KEY userId keySuffix; // 4.获取今天是本月的第几天 int dayOfMonth DateUtil.dayOfMonth(date); // 5.写入Redis SETBIT key offset 1 stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true); return Result.ok(); }
结果展示 三、连续签到统计功能实现
3.1、需求分析
问题1什么叫做连续签到天数 从最后一次(当前时间)签到开始向前统计直到遇到第一次未签到为止计算总的签到次数就是连续签到天数。 问题2如何得到本月到今天为止的所有签到数据 BITFIELD key GET u[dayOfMonth]0
问题3如何从后向前遍历每个bit位 与1做与运算就能得到最后一个bt位。随后右移一位下一个Bit位就成了最后一个Bit位。 3.2、代码实现
public Result signCount() {// Long userId UserHolder.getUser().getId();Long userId 999L; //暂时写死// 2.获取日期 使用hutool的日期时间工具-DateUtilDate date DateUtil.date();// 3.拼接keyString keySuffix DateUtil.format(date, :yyyyMM);String key USER_SIGN_KEY userId keySuffix;// 4.获取今天是本月的第几天int dayOfMonth DateUtil.dayOfMonth(date);// 5.获取本月截止今天为止的所有的签到记录返回的是一个十进制的数字 BITFIELD sign:999:202308 GET u18 0ListLong result stringRedisTemplate.opsForValue().bitField(key,BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));if (result null || result.isEmpty()) {// 没有任何签到结果return Result.ok(0);}//num为0直接返回0Long num result.get(0);if (num null || num 0) {return Result.ok(0);}// 6.循环遍历int count 0;while (true) {// 6.1.让这个数字与1做与运算得到数字的最后一个bit位 // 判断这个bit位是否为0if ((num 1) 0) {// 如果为0说明未签到结束break;}else {// 如果不为0说明已签到计数器1count;}// 把数字右移一位抛弃最后一个bit位继续下一个bit位num 1;}return Result.ok(count);} 3.3、结果展示
当天还没有签到统计 当天已经签到统计 四、源码获取方式 更多优秀文章请关注个人微信公众号或搜索“程序猿小杨”查阅。然后回复源码可以获取该项目对应的源码及表结构开箱即可使用。 说明后面redis相关操作的功能都会放在此文件夹中需要相关功能的只需要获取最新的资源替换项目即可。 如果大家对相关文章感兴趣可以关注微信公众号程序猿小杨会持续更新优秀文章!欢迎大家 分享、收藏、点赞、在看您的支持就是我坚持下去的最大动力谢谢!