1.Bitmap(位图)

Redis的Bitmap类型并不是一个独立的数据类型,而是对String类型的一种巧妙使用,允许开发者以位级别操作字符串中的数据。Bitmap可以视为一个巨大的位数组,每个位(bit)可以存储0或1的值,这使得Bitmap非常适合用于存储和操作大量的布尔值或者进行高效的统计计数。

Bitmap文持的最大位数是2^32位,它可以极大的节约存储空间,使用512M内存就可以存储多达42,9亿的字节信息(2^32=4294967296)

特点

  1. 空间效率:Bitmap极其节省空间。例如,一个整数占用4字节(32bit位),而使用Bitmap表示同样的32个布尔值只需要1字节。
  2. 灵活性:可以对每个位进行独立设置、清除、检查操作。
  3. 计算能力:支持按位与、或、异或等操作,以及位计数等高级操作,这对于统计和分析非常有用。
  4. 适用于计数和追踪:如网站用户是否登录、用户特征标记、事件发生频率统计等场景。

2.常用命令

  • SETBIT key offset value:设置位图中指定偏移量的值。
  • GETBIT key offset:获取位图中指定偏移量的值。
  • strlen key:获取该Bitmap所占用的字节数,而不是比特位中1的个数。
  • BITCOUNT key [start end]:计算位图中位值为1的个数,可选地限制在指定范围内。
  • BITOP operation destkey key [key ...]:对多个位图执行AND、OR、NOT、XOR操作,并将结果保存到destkey。
  • BITFIELD key [GET type offset] [SET type offset value] [...]:更复杂的位操作,可以一次执行多个位操作。

3.示例

3.1 SETBIT和GETBIT

SETBIT key offset value:设置位图中指定偏移量的值。

GETBIT key offset:获取位图中指定偏移量的值。

offset从0开始

127.0.0.1:6379> setbit k1 1 1
(integer) 0 # 返回值是设置前的值
127.0.0.1:6379> setbit k1 1 0
(integer) 1
127.0.0.1:6379> setbit k1 2 1 
(integer) 0
127.0.0.1:6379> setbit k1 3 3 # 值只能是0和1
(error) ERR bit is not an integer or out of range
127.0.0.1:6379> getbit k1 0
(integer) 0
127.0.0.1:6379> getbit k1 1
(integer) 0
127.0.0.1:6379> getbit k1 2
(integer) 1
127.0.0.1:6379> 

3.2 STRLEN

strlen key:获取该Bitmap所占用的字节数,而不是比特位中1的个数。

127.0.0.1:6379> setbit k1 7 1
(integer) 1
127.0.0.1:6379> strlen k1
(integer) 1
127.0.0.1:6379> setbit k1 8 0
(integer) 0
127.0.0.1:6379> strlen k1
(integer) 2
127.0.0.1:6379> 

不是字符串长度而是占据几个字节,超过8位后自己按照8位一组一byte再扩容

3.3 BITCOUNT

BITCOUNT key [start end]:计算位图中位值为1的个数,可选地限制在指定范围内。

127.0.0.1:6379> setbit k1 0 1
(integer) 0
127.0.0.1:6379> setbit k1 1 1
(integer) 0
127.0.0.1:6379> setbit k1 7 1
(integer) 0
127.0.0.1:6379> bitcount k1 
(integer) 3
127.0.0.1:6379> bitcount k1 0 3
(integer) 3
127.0.0.1:6379> bitcount k1 0 3 byte # 以byte为单位
(integer) 3
127.0.0.1:6379> bitcount k1 0 3 bit # 以bit为单位
(integer) 2
127.0.0.1:6379> 

3.4 BITOP

BITOP operation destkey key [key ...]:对多个位图执行AND(与)、OR(或)、XOR(异或)和NOT(非)操作,并将结果保存到destkey。

假设我们有两个Bitmap键use1user2,分别代表了两天内用户的在线状态,其中1表示在线,0表示离线。

他们三天中的在线状态如下:

127.0.0.1:6379> setbit user1 0 1
(integer) 0
127.0.0.1:6379> setbit user1 1 1
(integer) 0
127.0.0.1:6379> setbit user2 0 1
(integer) 0
127.0.0.1:6379> setbit user2 2 1
(integer) 0
127.0.0.1:6379> 

如果想要找出这两天都在线的用户,可以使用AND操作。

127.0.0.1:6379> bitop and k1 user1 user2
(integer) 1
127.0.0.1:6379> getbit k1 0
(integer) 1
127.0.0.1:6379> getbit k1 1
(integer) 0
127.0.0.1:6379> 

and操作: user1和user2对应位都是1的情况下才为1,否则为0。

如果我们想找出至少有一天在线的用户,可以使用OR操作。

127.0.0.1:6379> bitop or k2 user1 user2
(integer) 1
127.0.0.1:6379> bitcount k2
(integer) 3
127.0.0.1:6379> 

or操作: user1和user2只要有1,就是1.否则为0

如果我们要找出只在某一天在线,而不在另一天在线的用户,可以使用XOR操作。

127.0.0.1:6379> getbit k3 0
(integer) 0
127.0.0.1:6379> getbit k3 1
(integer) 1
127.0.0.1:6379> getbit k3 2
(integer) 1
127.0.0.1:6379> 

xor操作:user1和user2对应位不同时为1(即一位是1另一位是0)

另外,BITOP命令不直接支持NOT操作,因为NOT操作需要一个源位图和目标位图。但是,可以通过创建一个全1的Bitmap(假设长度与原Bitmap相同),然后使用XOR操作达到NOT的效果。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐