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是比较中最长字符串的长度。

相关推荐
&梧桐树夏3 小时前
【算法系列-链表】删除链表的倒数第N个结点
数据结构·算法·链表
QuantumStack3 小时前
【C++ 真题】B2037 奇偶数判断
数据结构·c++·算法
wclass-zhengge4 小时前
Redis篇(最佳实践)(持续更新迭代)
redis·缓存·bootstrap
wclass-zhengge4 小时前
数据结构篇(绪论)
java·数据结构·算法
Dylanioucn4 小时前
【分布式微服务云原生】探索Redis:数据结构的艺术与科学
数据结构·redis·分布式·缓存·中间件
何事驚慌4 小时前
2024/10/5 数据结构打卡
java·数据结构·算法
结衣结衣.4 小时前
C++ 类和对象的初步介绍
java·开发语言·数据结构·c++·笔记·学习·算法
大三觉醒push亡羊补牢女娲补天版4 小时前
数据结构之排序(5)
数据结构
TJKFYY4 小时前
Java.数据结构.HashSet
java·开发语言·数据结构
Code成立4 小时前
1、深入理解Redis线程模型
数据库·redis·bootstrap