redis–09–操作–Bitmaps


1、简介

  1. Bitmaps可以实现对位的操作(1位=8字节)
  2. Bitmaps本身不是一种数据类型, 实际上它就是字符串(key-value), 但是它可以对字符串value的位进行操作。可以把Bitmaps想象成一个以位为单位的数组, 数组的每个单元只能存储0和1, 数组的下标在Bitmaps中叫做偏移量。

redis bitmap写太多次数 redis bitmap操作_数据库

2、Bitmaps与set对比

假设网站有1亿用户, 每天独立访问的用户有5千万, 如果每天用集合类型和Bitmaps分别存储活跃用户可以得到表

set和Bitmaps存储一天活跃用户对比

数据类型

每个用户id占用空间

需要存储的用户量

全部内存量

set

64位

50000000

64位*50000000 = 400MB

Bitmaps

1位

100000000

1位*100000000 = 12.5MB

很明显, 这种情况下使用Bitmaps能节省很多的内存空间, 尤其是随着时间推移节省的内存还是非常可观的。

set和Bitmaps存储独立用户空间对比

数据类型

一天

一月

一年

set

400MB

12GB

144GB

Bitmaps

12.5MB

375MB

4.5GB

但Bitmaps并不是万金油, 假如该网站每天的独立访问用户很少, 例如只有10万(大量的僵尸用户), 那么两者的对比如下表所示, 很显然, 这时候使用Bitmaps就不太合适了, 因为基本上大部分位都是0。

set和Bitmaps存储一天活跃用户对比(独立用户比较少)

数据类型

每个用户id占用空间

需要存储的用户量

全部内存量

set

64位

100000

64位*100000 = 800KB

Bitmaps

1位

100000000

1位*100000000 = 12.5MB

3、操作

3.1、setbit key off setvalue

1.设置Bitmaps中某个偏移量的值(0或1)
2.offset:偏移量从0开始

3.1.1、案例

每个独立用户是否访问过网站存放在Bitmaps中,将访问的用户记做1,没有访问的用户记做0,用偏移量作为用户的id。

设置键的第offset个位的值(从0算起),假设现在有20个用户,userid=1,6,11,15,19的用户对网站进行了访问,那么当前Bitmaps初始化结果如图

redis bitmap写太多次数 redis bitmap操作_redis_02

127.0.0.1:6379> setbit users:20220202  1  1 
(integer) 0
127.0.0.1:6379> setbit users:20220202  6  1
(integer) 0
127.0.0.1:6379> setbit users:20220202  11  1 
(integer) 0
127.0.0.1:6379> setbit users:20220202  15  1 
(integer) 0
127.0.0.1:6379> setbit users:20220202  19  1 
(integer) 0
127.0.0.1:6379>

users:20220202代表2022-02-02这天的独立访问用户的Bitmaps

很多应用的用户id以一个指定数字(例如10000000)开头,直接将用户id和Bitmaps的偏移量对应会造成一定的浪费,因为在第1次初始化Bitmaps时,假如偏移量非常大,那么整个初始化过程执行会比较慢,可能会造成Redis的阻塞。

通常的做法是每次做setbit操作时将用户id减去这个指定数字。

3.2、getbit key offset

获取键的第offset位的值(从0开始算)

3.2.1、案例

获取id=15,id=8的用户是否在2022-02-02这天访问过,返回0说明没有访问过:

127.0.0.1:6379> getbit users:20220202 15
(integer) 1
127.0.0.1:6379> getbit users:20220202 8
(integer) 0
127.0.0.1:6379>

3.3、bitcount key [start end]

  1. 统计字符串从start字节到end字节比特值为1的数量
  2. start、end是指bit组的字节的下标数

3.3.1、案例

计算2022-02-02这天的独立访问用户数量

计算用户id在第1个字节到第3个字节之间的独立访问用户数

start和end代表起始和结束字节数,下面操作计算用户id在第1个字节到第3个字节之间的独立访问用户数

127.0.0.1:6379> bitcount users:20220202 1 3
(integer) 3
127.0.0.1:6379>

1,6,11,15,19 对应的字节数组如下

01000010 00010001 00010000

对应字节数组【0,1,2】

第1个字节到第3个字节就是:00010001 00010000
这里面有3个1,所以返回3,对应的用户id也就是11,15,19。

3.3.2、举例

K1 【01000001 01000000  00000000 00100001】,对应【0,1,2,3】
bitcount K1 1 2

统计下标1、2字节组中bit=1的个数,即

01000000  00000000

结果:1

bitcount K1 1 3

统计下标1、3字节组中bit=1的个数,即

01000000  00000000 00100001

结果:3

bitcount K1 0 -2

统计下标0到下标倒数第2,字节组中bit=1的个数,即

01000001  01000000   00000000

结果:3

3.4、bitop and(or/not/xor) destkey [key…]

bitop是一个复合操作,它可以做多个Bitmaps的and(交集)、or(并集)、not(非)、xor(异或)操作,并将结果保存在destkey中。

3.4.1、

2022-02-01日访问网站的userid=1,2,5,9。

127.0.0.1:6379> setbit users:20220201 1 1
(integer) 0
127.0.0.1:6379> setbit users:20220201 2 1
(integer) 0
127.0.0.1:6379> setbit users:20220201 5 1
(integer) 0
127.0.0.1:6379> setbit users:20220201 9 1
(integer) 0
127.0.0.1:6379>

2022-02-02日访问网站的userid=0,1,4,9。

(integer) 0
127.0.0.1:6379> setbit users:20220202 0 1
(integer) 0
127.0.0.1:6379> setbit users:20220202 1 1
(integer) 0
127.0.0.1:6379> setbit users:20220202 4 1
(integer) 0
127.0.0.1:6379> setbit users:20220202 9 1
(integer) 0
127.0.0.1:6379>

计算出两天都访问过网站的用户数量

127.0.0.1:6379> bitop and  desc users:20220201 users:20220202
(integer) 2
127.0.0.1:6379>
原理
users:20220201--> 01100100 01000000 
users:20220202--> 11010000 01000000 
and 
desc------------> 01000000 01000000

计算出任意一天都访问过网站的用户数量(例如月活跃就是类似这种),可以使用or求并集

127.0.0.1:6379> bitop or  desc2 users:20220201 users:20220202
(integer) 2
127.0.0.1:6379>