1、数据结构

  • bitmap:位图,是由01组成的 bit 串,很显然这种数据结构是非常节省存储空间的。按照存储空间来算1个byte有8个bit位,其中每一个比特位都可以使用0 或者 1来表示某种状态!
  • redis中bitmap最大的bit数量 = 2^32-1 bit;也就是说单个bitmap的key最大有512MB。
  • bitmap在c++语言中有一个孪生兄弟bitset,一般用于做二进制压缩(节约空间),可以简单的认为bitmap就是一个由01构成的数组,数组最大长度是int大小。



2、使用场景

2.1、签到打卡
  • 由于bitmap的值只有0或1,因此bitmap可以用于统计某个用户一年的签到打卡的情况。按照1年365天算,只需要365bit 大约 46byte。
  • 如果使用bool值表示某个用户的打卡情况,那么一年下来需要365byte,也就是说如果使用bitmap,只要这个用户一年打卡的数量超过46天,那么使用bitmap就能够节省空间。(如果使用int那么节约的量级更大!)


2.2、短视频用户活跃数量
  • 截止到目前我认识的人没有一个人不刷短视频,像抖音平台每天的用户活跃量是非常高的,如果使用bitmap的每一位表示一个用户,那么空间的节约将会是超大的降维打击。
  • 可以假设抖音每天都使用一个128mb的bitmap(2^31)大约可以表示10亿用户,显然抖音并没有这么多用户,但是都应每天活跃用户小几个亿估计问题不大,那么一天使用128mb完全能够满足统计所有用户的活跃量。
  • 如果换算成使用bool或者其他基本数据类型来表示那么也需要10亿byte…


虽然bitmap可以节约空间,但是它也并没有想象的那么友好;显然上面两种情况都是基于流量比较大的情况,当用户流量比较小或者用户活跃度较低时可能bitmap会反向浪费空间。




3、基本使用

3.1、设置index值

设置值的时候只能设置为0或者1,其他值将会报错。

语法:setbit key index 0/1
setbit monday 3 1 
setbit monday 5 1
setbit monday 9 1 
setbit monday 20 1

结果: 0000100    一个字节



3.2、获取index值
语法: getbit key index
getbit monday 0
getbit monday 5

结果:0 1



3.3、统计字节区间1的数量
  • start和end可以不给出,此时表示统计整个key中1的数量
  • 如果给出start和end,start和end表示的是字节区间,不是比特区间。1字节 = 8比特
  • 如果给出负数,表示倒数第几个;例如end = -2,表示从start开始 ~ 倒数第二个字节区间中1的数目。
语法: bitcount key [start end]

bitcount monday
结果: 4 (3 5 9 20)

bitcount monday 0 1
结果: 3 (3 5 9)

bitcount monday 0 -2
结果: 3 (3 5 9)此时总共3个字节,倒数第二个字节即第二个字节。



3.4、交集操作
  • monday有3、5、9、20设置为1
  • tuesday有1、5、13、20设置为1
语法: bitop and destkey key1 key2 ...


bitop and mon_tue monday tuesday
结果: mon_tue中只有5 20为1



3.5、并集操作
  • monday有3、5、9、20设置为1
  • tuesday有1、5、13、20设置为1
语法: bitop or destkey key1 key2 ...


bitop or mon_tue monday tuesday
结果: mon_tue中1、3、5、9、13、20都为1



3.6、异或操作
  • monday有3、5、9、20设置为1
  • tuesday有1、5、13、20设置为1
  • 异或操作是不能同时为1
语法: bitop xor destkey key1 key2 ...


bitop xor mon_tue monday tuesday
结果: mon_tue中1、3、9、13为1
3.7、非操作
  • monday有3、5、9、20设置为1
  • 非操作只能使用单一的key,不能同时多个key
语法: bitop not destkey key1

bitop not mon_tue monday
结果: mon_tue中除了3、5、9、20为0,其他20个bit位都是1。(最大字节也就是3)