redis bitmap用户签到 (redisbitmap原理)

Redis Bitmap基础

Redis Bitmap(位图)是另一种将字符串类型数据视为位集合或位向量的方法。因此,位图的底层数据结构是一个字符串,其中使用计算机内存中的 0 和 1 数组存储字符串。Redis 位图支持位图中给定偏移量的位值的检索和交替。此外,它还提供了对存储在给定键处的多个字符串执行按位运算(如 AND、OR、NOT 和 XOR)的命令。

redisbitmap签到功能设计与实现,redisbitmap用户签到

如图所示,存储在 Redis 数据库中的字符串值可以视为位图。我们可以对存储在给定键上的多个 Redis 字符串执行按位运算,如下所示:

AND运算

下图说明了两个给定字符串的按位与运算的工作原理。在这个例子中,我们将使用字符串 A 和 B 来执行按位与运算。

redisbitmap签到功能设计与实现,redisbitmap用户签到

OR运算

让我们对上一个示例中的两个相同字符串执行按位或运算。

redisbitmap签到功能设计与实现,redisbitmap用户签到

如图所示,生成的位图是 1000011,它是字母 C 的 ASCII 表示。

XOR运算

按位异或运算如下图所示:

redisbitmap签到功能设计与实现,redisbitmap用户签到

NOT操作

NOT 运算符在 Redis 按位运算中用作一元运算符。因此,它只需要一个字符串值作为输入。

redisbitmap签到功能设计与实现,redisbitmap用户签到

对字符串 A 的按位 NOT 运算返回 \xbe 十六进制值并且没有关联的可打印 ASCII 值。

位指令

Redis 引入了 BITOP 命令,用于对存储在给定键中的一个或多个字符串(位图)执行前面讨论的位运算。此命令以 O(N) 时间复杂度运行,其中 N 是比较中最长字符串的长度,这比其他位图操作慢得多。此命令执行指定的按位运算并将结果位图(字符串)存储在指定的目标键中。

BITOP 命令的语法如下:

BITOP bitwise_operation destination_key bitmap_key [ bitmap_key ... ]

BITOP 命令返回一个整数值,它是生成的位图的大小。结果位图的大小等于最长输入位图的大小。

在某些情况下,输入位图包含不同大小的字符串。因此,BITOP 命令将所有其他比最长字符串短的输入字符串处理成零填充,直到达到最长字符串的大小。类似地,不存在的位图键被视为零字节字符串,其大小与最长的输入字符串相同。

用例 - 统计给定日期内网站的活跃用户

假设网站所有者对每周登录网站的活跃用户感兴趣。在这种情况下,位图是存储每日访问量的理想选择。可以使用位图中的偏移量来表示每个用户。此外,每天可以使用具有唯一 ID 的单独位图,如下图所示:

redisbitmap签到功能设计与实现,redisbitmap用户签到

我们为前三天(星期日、星期一和星期二)创建位图,以保存每个用户的访问状态。SET 命令可用于创建每个位图,如下所示:

创建第一个位图,该位图由密钥 visit:2022:08:4:SUN 标识。 因此,第一个用户由偏移量 0 标识。假设与用户 ID 0 关联的用户在周日访问了该网站。因此,偏移量 0 设置为 1,如下所示:

setbit visit:2022:08:4:SUN 0 1

同理,用户ID为1、2、3、4的用户的访问状态也相应设置。

setbit visit:2022:08:4:SUN 1 0

setbit visit:2022:08:4:SUN 2 1

setbit visit:2022:08:4:SUN 3 0

setbit visit:2022:08:4:SUN 4 0

使用 GETBIT 命令检查每个用户的位值,如下所示:

getbit visit:2022:08:4:SUN 0

getbit visit:2022:08:4:SUN 1

getbit visit:2022:08:4:SUN 2

getbit visit:2022:08:4:SUN 3

getbit visit:2022:08:4:SUN 4

redisbitmap签到功能设计与实现,redisbitmap用户签到

同样,我们可以创建位图来存储星期一和星期二的用户访问,这些访问由键 visit:2022:08:5:MON visit:2022:08:6:TUE 标识。

网站所有者的需求是获取从星期日、星期一或星期二起至少一天访问该网站的用户。可以使用 BITOP 命令获取此类信息,如下所示。OR 按位运算非常适合检查三天中至少有一天访问该站点的用户。

bitop OR atleaseonevisituser visit:2022:08:4:SUN visit:2022:08:5:MON visit:2022:08:6:TUE

我们对前面创建的三个位图进行了按位或操作。生成的位图存储在键 atleastonevisituser 中。使用 GET 命令检查生成的字符串或位图,如下所示:

get atleaseonevisituser

redisbitmap签到功能设计与实现,redisbitmap用户签到

返回的位图或字符串的十六进制值为 \xb0,表示 ASCII 中的度数符号。让我们使用 GETBIT 命令检查存储在目标键 atleaseonevisituser 中的字符串的每一位。

getbit atleaseonevisituser 0

getbit atleaseonevisituser 1

getbit atleaseonevisituser 2

getbit atleaseonevisituser 3

getbit atleaseonevisituser 4

redisbitmap签到功能设计与实现,redisbitmap用户签到

正如我们在图中输出中所示,生成的位图如下所示:

1 | 0 | 1 | 1 | 0

偏移量 0 与用户 ID 0 关联,偏移量 1 与用户 ID 1 关联,依此类推。根据按位或运算的结果,只有三个用户在上述三天中至少有一天访问过该网站。存储在偏移量1和4的用户ID为1和4的用户在周日、周一或周二没有访问该网站。

结论

总之,Redis 位图是一个由 0 和 1 组成的数组,其中每个位由一个偏移值标识。如前所述,BITOP 命令用于对指定的位图或字符串执行按位运算,例如 OR、AND、XOR 和 NOT。如用例所示,结果字符串存储在指定的键中。当最长字符串的大小增加时,此命令非常慢。总体而言,BITOP 命令可用于识别给定时间段内的网站访问统计和应用程序使用统计信息。