Redis Bitmaps 数据结构模型位操作

Bitmaps 数据结构模型

Bitmap 本身不是一种数据结构,实际上它就是字符串,但是它可以对字符串的位进行操作。 比如 "abc" 对应的 ASCII 码分别是 97、98、99。对应的二进制分别是 01100010、01100010、01100011, 如下所示:

shell 复制代码
    a        b         c
+--------+--------+--------+
|01100001|01100010|01100011|
+--------+--------+--------+

位图的最大优点之一是它们在存储信息时通常可以极大地节省空间。

例如,在一个用增量用户 ID 表示不同用户的系统中,仅使用 512 MB 内存就可以记住 40 亿个用户的单个比特信息。

1bit * 4,000,000,000 = 500,000,000 B = 488,281.25 KB = 476.8 MB

GETBIT 仅返回指定索引处的位的值。超出范围的位(寻址超出目标密钥中存储的字符串长度的位)始终被视为零。

shell 复制代码
root@ubuntu-x64_01:~#  redis-cli --no-auth-warning -h 192.168.88.11 -p 6380 -a "******" get k1 
"a"

root@ubuntu-x64_01:~#  redis-cli --no-auth-warning -h 192.168.88.11 -p 6380 -a "******" --eval getbit.lua k1
"01100001"

setbit

设置健的第offset个位的值(从0算起),如有8个用户 userid = 0, 1, 2, 3, 4, 5, 6,7 , 其中用户 1, 3, 5 对网站进行了访问 , 那么Bitmaps初始化如下:

shell 复制代码
setbit key offset value
shell 复制代码
192.168.88.11:6380> setbit users:2023-12-09 1 1
(integer) 0
192.168.88.11:6380> setbit users:2023-12-09 3 1
(integer) 0
192.168.88.11:6380> setbit users:2023-12-09 5 1
(integer) 0

# 获取当前哪些用户访问了 , 其中 1 表示访问过的用户 
root@ubuntu-x64_01:~#   /redis-cli --no-auth-warning -h 192.168.88.11 -p 6380 -a "******" --eval getbit.lua users:2023-12-09
"01010100"

getbit

获取健的第offset位的值(从0算起), 如下获取 user 5 是否在 2023-12-09 访问过, 1表示访问,0表示没有访问,如果offset不存在,返回结果也是0, 超出范围的位始终被视为零。

shell 复制代码
192.168.88.11:6380> getbit users:2023-12-09 5
(integer) 1

bitcount

获取Bitmaps指定范围值为1的个数,如统计 2023-12-09 这天访问的用户数量

shell 复制代码
192.168.88.11:6380> bitcount users:2023-12-09
(integer) 3

bitop

bitmaps之前的运算,它可以做and(交集)、or(并集)、not(非)、xor(异或),并将结果保存在 destkey ,如计算 2023-12-09、2023-12-10 两天都访问过的用户数量

shell 复制代码
root@ubuntu-x64_01:~#  redis-cli  --no-auth-warning -h 192.168.88.11 -p 6380 -a "******" --eval getbit.lua users:2023-12-09
"01010100"
root@ubuntu-x64_01:~#  redis-cli  --no-auth-warning -h 192.168.88.11 -p 6380 -a "******" --evalgetbit.lua users:2023-12-10
"01100110"

192.168.88.11:6380> bitop and users:2023-12-09_10 users:2023-12-09 users:2023-12-10
(integer) 1

192.168.88.11:6380> bitcount users:2023-12-09_10
(integer) 2

root@ubuntu-x64_01:~#  redis-cli --no-auth-warning -h 192.168.88.11 -p 6380 -a "******" --eval getbit.lua users:2023-12-09_10
"01000100"

小结

将位图拆分为多个键很简单,例如为了对数据集进行分片,并且通常最好避免使用巨大的键。要将位图拆分到不同的键上,而不是将所有位设置为一个键,一个简单的策略就是为每个键存储 M 位,并使用 获取键名称和bit-number/M在键(bit-number MOD M)内寻址的第 N 位。

假设 M=10 , 约100个用户(有点少,仅用作举例):

则 第91个用户寻址如下:健名称: 91 MOD 10 = 1 即 key = user1 , N = 91/10 = 9

则 第65个用户寻址如下:健名称: 65 MOD 10 = 5 即 key = user5 , N = 65/10 = 6

SETBIT 、 GETBIT 、BITFIELD 均为 O(1)。

BITCOUNT、BITOP、BITPOS 是 O(n),其中n是比较中最长字符串的长度。

相关推荐
煎饼小狗14 分钟前
Redis五大基本类型——Zset有序集合命令详解(命令用法详解+思维导图详解)
数据库·redis·缓存
Lenyiin18 分钟前
02.06、回文链表
数据结构·leetcode·链表
爪哇学长21 分钟前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
爱摸鱼的孔乙己23 分钟前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
烦躁的大鼻嘎1 小时前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode
C++忠实粉丝1 小时前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
秋意钟2 小时前
缓存雪崩、缓存穿透【Redis】
redis
简 洁 冬冬2 小时前
046 购物车
redis·购物车
daiyang123...3 小时前
测试岗位应该学什么
数据结构
soulteary3 小时前
突破内存限制:Mac Mini M2 服务器化实践指南
运维·服务器·redis·macos·arm·pika