redis位图法bitmap统计活跃用户
位图法
位图(bitmap),就是用位(bit)来表示存放的某种状态,如开关,有无。在redis中,字符串是以二进制的形式存储的,因此位图在redis中并不是一种数据类型,而是一种字符串的表现形式。位图中每个元素在内存中占用1位,所以可以节省存储空间。
相关命令
1、SETBIT key offset value
该命令时间复杂度: O(1),效率极高;
对 key
所储存的字符串值,设置或清除指定偏移量上的位(bit)。
位的设置或清除取决于 value
参数,可以是 0
也可以是 1
。
当 key
不存在时,自动生成一个新的字符串值。
字符串会进行伸展以确保它可以将 value
保存在指定的偏移量上。当字符串值进行伸展时,空白位置以 0
填充。
offset
参数必须大于或等于 0
,小于 2^32 (bit 映射被限制在 512 MB 之内)。
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
作为输入。
3、BITCOUNT key [start] [end]
该命令时间复杂度: O(N)
计算给定字符串中,被设置为 1 的比特位的数量。
一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。
start 和 end 参数的设置和 GETRANGE key start end 命令类似,都可以使用负数值: 比如 -1 表示最后一个字节, -2 表示倒数第二个字节,以此类推。
不存在的 key 被当成是空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0 。
统计活跃用户
为了统计每日登录的用户数,建立了一个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}
以下使用命令演示一周的用户登录情况:
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
统计一周内连续登录用户:
localhost:6379:0>BITOP AND result mon tue wed thu fri sat sun
13
localhost:6379:0>BITCOUNT result
2
使用 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 上线的总天数。