redis位图法bitmap统计活跃用户

1、位图法

位图(bitmap),就是用位(bit)来表示存放的某种状态,如开关,有无。在redis中,字符串是以二进制的形式存储的,因此位图在redis中并不是一种数据类型,而是一种字符串的表现形式。位图中每个元素在内存中占用1位,所以可以节省存储空间。

2、相关命令

2.1、SETBIT key offset value

该命令时间复杂度: O(1),效率极高;
对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
位的设置或清除取决于 value 参数,可以是 0 也可以是 1 。
当 key 不存在时,自动生成一个新的字符串值。
字符串会进行伸展以确保它可以将 value 保存在指定的偏移量上。当字符串值进行伸展时,空白位置以 0 填充。
offset 参数必须大于或等于 0 ,小于 2^32 (bit 映射被限制在 512 MB 之内)。

2.2、BITOP operation destkey key [key …]

该命令时间复杂度: O(N)
对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种:
BITOP AND destkey key [key …] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。
BITOP OR destkey key [key …] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。
BITOP XOR destkey key [key …] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。
BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey 。

除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入。

2.3、BITCOUNT key [start] [end]

该命令时间复杂度: O(N)
计算给定字符串中,被设置为 1 的比特位的数量。
一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。
start 和 end 参数的设置和 GETRANGE key start end 命令类似,都可以使用负数值: 比如 -1 表示最后一个字节, -2 表示倒数第二个字节,以此类推。
不存在的 key 被当成是空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0 。

3、统计活跃用户

为了统计每日登录的用户数,建立了一个bitmap, 每一位标识一个用户ID。

当某个用户登录了网站或执行了某个操作,就在bitmap中把标识此用户的位置为1,未登录默认为0,

然后进行and操作,即可统计活跃用户数。

redis key可以设计成:时间周;

offset 用user_id。

用户登录数据如下:

100 、101、102、103 代表用户user_id
周一:{100,101,102,103}
周二:{101,102,103}
周三:{101,102}
周四:{100,101,102}
周五:{100,101,102,103}
周六:{101,102,103}
周日:{100,101,102}

一周内连续登录的用户有2个:{101,102}

以下使用命令演示一周的用户登录情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
localhost:6379:0>SETBIT mon 100 1
0

localhost:6379:0>SETBIT mon 101 1
0

localhost:6379:0>SETBIT mon 102 1
0

localhost:6379:0>SETBIT mon 103 1
0

localhost:6379:0>SETBIT tue 101 1
0

localhost:6379:0>SETBIT tue 102 1
0

localhost:6379:0>SETBIT tue 103 1
0

localhost:6379:0>SETBIT wed 101 1
0

localhost:6379:0>SETBIT wed 102 1
0

localhost:6379:0>SETBIT thu 100 1
0

localhost:6379:0>SETBIT thu 101 1
0

localhost:6379:0>SETBIT thu 102 1
0

localhost:6379:0>SETBIT fri 100 1
0

localhost:6379:0>SETBIT fri 101 1
0

localhost:6379:0>SETBIT fri 102 1
0

localhost:6379:0>SETBIT fri 103 1
0

localhost:6379:0>SETBIT sat 101 1
0

localhost:6379:0>SETBIT sat 102 1
0

localhost:6379:0>SETBIT sat 103 1
0

localhost:6379:0>SETBIT sun 100 1
0

localhost:6379:0>SETBIT sun 101 1
0

localhost:6379:0>SETBIT sun 102 1
0

统计一周内连续登录用户:

1
2
3
4
5
localhost:6379:0>BITOP AND result mon tue wed thu fri sat sun
13

localhost:6379:0>BITCOUNT result
2

4、使用 bitmap 实现用户上线次数统计

假设现在我们希望记录自己网站上的用户的上线频率,比如说,计算用户 A 上线了多少天,用户 B 上线了多少天,诸如此类,以此作为数据,从而决定让哪些用户参加 beta 测试等活动 —— 这个模式可以使用 SETBIT key offset value 和 BITCOUNT key [start] [end] 来实现。

比如说,每当用户在某一天上线的时候,我们就使用 SETBIT key offset value ,以用户名作为 key ,将那天所代表的网站的上线日作为 offset 参数,并将这个 offset 上的value设置为 1 。

举个例子,如果今天是网站上线的第 100 天,而用户 peter 在今天阅览过网站,那么执行命令 SETBIT peter 100 1 ;如果明天 peter 也继续阅览网站,那么执行命令 SETBIT peter 101 1 ,以此类推。

当要计算 peter 总共以来的上线次数时,就使用 BITCOUNT key [start] [end] 命令:执行 BITCOUNT peter ,得出的结果就是 peter 上线的总天数。

参考资料:http://redisdoc.com/bitmap/index.html


redis位图法bitmap统计活跃用户
https://river106.cn/posts/81f27101.html
作者
river106
发布于
2020年2月8日
许可协议