Redis 的 bitmap 实现签到系统?
答: 主要讲一下 Redis 原生的 bitmap 的使用方法,以及如何使用 bitmap 来实现签到功能
先来看一下如何使用 redis bitmap 的原生命令实现签到功能:
- 签到
我们先来设计 key:userid:yyyyMM
,那么假如 usera 在2023年10月3日和2023年10月4日签到的话,使用以下命令:
setbit key offset value
:
在3日签到的话,偏移量应该设置为2,则签到之后为 001
在4日签到的话,偏移量应该设置为3,则3日、4日签到后为0011
(第3位和第4位都是1,表示这两天签到了)
在31日签到的话,偏移量应该设置为30,表示向右偏移30位
127.0.0.1:6379> setbit userx:202310 2 1
(integer) 0
127.0.0.1:6379> setbit userx:202310 3 1
(integer) 0
127.0.0.1:6379> setbit userx:202310 30 1
(integer) 0
- 查看2023年10月哪些天签到了,10月有31天,所以使用
u31
(31位无符号整数),后边偏移量为0
127.0.0.1:6379> bitfield userx:202310 get u31 0
1) (integer) 402653185
通过 bitfield [key] get u31 0
获取了31位的无符号整数,将该整数402653185
转为二进制如下:(可以发现从左向右第4位和第5位位1,表示这两天签到了,也就是3号签到的时候,在setbit key value offset
中,偏移量设置了为3,所以向右偏移3为,在第4位上)
402653185 十进制
0011000000000000000000000000001 二进制
通过取出来这个无符号整数,我们在代码中就可以通过位运算来判断某一天是否签到,可以看出,第3、4、31位都是1,表明在这三天都进行了签到
那么如果今天是10月26日,我们想知道10月1日-10月26日有哪些天进行签到,使用如下命令:
127.0.0.1:6379> bitfield userx:202310 get u26 0
1) (integer) 12582912
将 12582912
转为二进制为:
26位无符号整数:
00110000000000000000000000
那么我们在计算连续签到的次数就可以使用以下方法:
public Integer getContinuousSignCount() {
/*
假如今天是 10月26日
假如通过 redis 的 bitfield userx:202310 get u26 0 命令得到了从1日-26日的签到数据为:12582912
*/
Long v = 12582912;
// 这里 26 为今天的日期
Integer signCount = 0;
for (int i = 0; i < 26; i ++) {
if (v & 1 == 0) return signCount;
signCount ++;
v >>= 1;
}
}
标签:10,26,签到,Redis,202310,bitmap,userx
From: https://blog.51cto.com/u_16186397/8748515