redis的bitmap数据类型使用(亿级海量数据统计解决方案)

124 阅读5分钟

文章目录

写在前面

我们现在有几亿个数据,数据状态都是1或者0两个状态,比如用户签到次数、或者登录次数等。
需要用什么数据类型存储呢?

如果我们需要记录某一用户在一年中每天是否有登录我们的系统这一需求该如何完成呢?如果使用KV存储,每个用户需要记录365个,当用户量上亿时,这所需要的存储空间是惊人的。

Redis 为我们提供了bitmap(位图)这一数据结构,每个用户每天的登录记录只占据一位,365天就是365位,仅仅需要46字节就可存储,极大地节约了存储空间。

bitmap的出现就是为了大数据量而来的,但是前提是统计的这个大数据量每个的状态只能有两种,因为每一个bit位只能表示两种状态。

Bitmap 本身是用 String 类型作为底层数据结构实现的一种统计二值状态的数据类型。String 类型是会保存为二进制的字节数组,所以,Redis 就把字节数组的每个 bit 位利用起来,用来表示一个元素的二值状态。你可以把 Bitmap 看作是一个 bit 数组。

bitmap(位图)基本命令

Bitmap 提供了 GETBIT/SETBIT 操作,使用一个偏移值 offset 对 bit 数组的某一个 bit 位进行读和写。不过,需要注意的是,Bitmap 的偏移量是从 0 开始算的,也就是说 offset 的最小值是 0。当使用 SETBIT 对一个 bit 位进行写操作时,这个 bit 位会被设置为 1。Bitmap 还提供了 BITCOUNT 操作,用来统计这个 bit 数组中所有“1”的个数。

重点!bitset的offset是偏移量!并不是单纯的数字,这点大家要搞清楚。

SETBIT命令

SETBIE用来设置或清除存储在键处的字符串值的偏移位,其返回值是原来位上存储的值。key 在初始状态下所有的位都为 0 。

基本格式:

SETBIT key offset value

基本使用:

# 设置2022年9月1号张三登录状态,返回值为偏移位原值
127.0.0.1:6379> setbit login:zhangsan:202209 1 1
(integer) 0

# 设置2022年9月2号张三登录状态
127.0.0.1:6379> setbit login:zhangsan:202209 2 1
(integer) 0

# 设置2022年9月3号张三登录状态
127.0.0.1:6379> setbit login:zhangsan:202209 3 0
(integer) 0

# 用普通get方式获取值,我们发现获取不到,只能使用bitget命令获取
127.0.0.1:6379> get  login:zhangsan:202209
"`"

GETBIT命令

GETBIT 用来获取存储在键处的字符串值中偏移位置的位值。

基本格式:

GETBIT key offset

基本使用:

# 获取2022年9月1号张三登录状态
127.0.0.1:6379> getbit login:zhangsan:202209 1
(integer) 1

BITCOUNT命令

BITCOUNT 用来统计指定区间内,值为1的个数。

基本格式:

BITCOUNT key [start end]

基本使用:

# 统计2022年9月张三登录次数
127.0.0.1:6379> bitcount login:zhangsan:202209
(integer) 2

可选参数
BITCOUNT 命令可以选择特定的 byte 范围计数,具体如下(注意start和end指的是字节,不是位):

  • start:设置位索引起始位置(包含该位置计数),第一个位置以 0 开始,start 参数需和 end 参数同时设置才合法。
  • end:设置位索引结束位置(包含该位置计数),end 参数需和 start 参数同时设置才合法。
    在这里插入图片描述
    注:起始从0开始。
# 获取第0-0个字节中值为1的数量
127.0.0.1:6379> bitcount testcount 0 0
(integer) 3
# 获取第0-1个字节中值为1的数量
127.0.0.1:6379> bitcount testcount 0 1
(integer) 5
# 获取第0-2个字节中值为1的数量
127.0.0.1:6379> bitcount testcount 0 2
(integer) 5
# 获取第0-13个字节中值为1的数量
127.0.0.1:6379> bitcount testcount 0 13
(integer) 6

BITOP 命令

对一个或多个保存二进制位的字符串 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 作为输入。

# 分别设置两组bit值
127.0.0.1:6379> setbit bit1 0 1
(integer) 0
127.0.0.1:6379> setbit bit1 3 1
(integer) 0
127.0.0.1:6379> setbit bit1 5 1
(integer) 0
127.0.0.1:6379>
127.0.0.1:6379> setbit bit2 1 1
(integer) 0
127.0.0.1:6379> setbit bit2 2 1
(integer) 1
127.0.0.1:6379> setbit bit2 6 1
(integer) 1
# 执行bitop add操作
127.0.0.1:6379> bitop and bitand bit1 bit2
(integer) 1
127.0.0.1:6379> bitcount bitand
(integer) 0

# 执行bitop or操作
127.0.0.1:6379> bitop or bitor bit1 bit2
(integer) 1
127.0.0.1:6379> bitcount bitor
(integer) 6

# 执行bitop xor操作
127.0.0.1:6379> bitop xor bitxor bit1 bit2
(integer) 1
127.0.0.1:6379> bitcount bitxor
(integer) 6

# 执行bitop not操作
127.0.0.1:6379> bitop not bit1not bit1
(integer) 1
127.0.0.1:6379> bitcount bit1not
(integer) 5
127.0.0.1:6379>
127.0.0.1:6379> bitop not bit2not bit2
(integer) 1
127.0.0.1:6379> bitcount bit2not
(integer) 5

注意注意!!!!setbit设置的是偏移量!