文章目录

  • 简介
  • 操作
  • 访问网站
  • 对比

简介

  1. 现在计算机用二进制(位)作为信息的基础单位,1个字节等于8位
  1. 例如 abc字符串是有3个字节组成,但实际在计算机存储时将其用二进制表示
  2. abc分别对应ASCII码分别是 97、98、99,对应的二进制分别是01100001/01100010/01100011,如下图

redis lpush byte数组 redis数据类型bitmap_redis


2. 合理的使用操作位能够有效的提高内存的使用率和开发效率

3. redis提供了Bitmaps这个数据类型,可以实现对于为的操作

1. Bitmaps本身不是一种数据类型,实际上他就是字符串(key-value),但是他可以对于字符串的位进行操作

2. Bitmaps单独提供了一套命令,所以在redis中使用Bitmaps和使用字符串的方法不太相同。可以把Bitmaps想象成一个以位为单位的数组,数组的每个单位只能存储0,1,数组的下标在Bitmaps中叫做偏移量,如下图

redis lpush byte数组 redis数据类型bitmap_1024程序员节_02

操作

  • setbit<key><offset><value>设置Bitmaps中某个偏移量的值(0或1),其中offset是从0开始的
  • 在第一次设置Bitmaps的时候,如果偏移量比较大,俺么整个初始化的活成会比较慢,就会造成redis的阻塞

访问网站

假设这个时候有20个用户,记录这20用于是否访问了网站,我们可能会做如下操作

  1. 其中userid从0开始,userid为 1,6,11,15,19的用户对于网站进行了访问,那么他最终的结果应该是如下
  2. 我们会做如下的操作

redis lpush byte数组 redis数据类型bitmap_数据类型_03

  • 其中,键unique:users:20221022表示2022-10-22这一天对立访问用的用户
  • 下标对应着userid

注意

  1. 很多应用的用户的id,以一个指定的数字开头(如10000),直接将用户id和Bitmaps的偏移量对应势必会造成一定的浪费,通常的做法是每次做setbit操作是将用户的id减去这个指定的数字

  • getbit<key><offset>:查询Bitmaps中某个偏移量的值

接着增加的例子,我们可以看看2022-10-22这天id为9的用户是否访问了网站

redis lpush byte数组 redis数据类型bitmap_redis lpush byte数组_04


他返回的是0,说明他并没有访问

  • bitcount key [start end]:统计从start位置到end位置的比特值为1的数量

redis lpush byte数组 redis数据类型bitmap_偏移量_05

  • bitop and(or/not/xor) <destkey> [key…]:他是一个复合操作,可以用作多个Bitmaps的and(交集)/or(并集)/not(非)/xor(异或),并将操作结果存到destkey中

对比

Bitmap与set对比

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

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

数据类型

每个用户id占用空间

需要存储的用户量

全内存量

集合类型

64位

50000000

64位*50000000 = 400MB

Bitmaps

1位

100000000

1位*100000000 = 12.5MB

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

数据类型

一天

一个月

一年

集合类型

400MB

12GB

144GB

Bitmaps

12.5MB

375MB

4.5GB

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

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

数据类型

每个userid占用空间

需要存储的用户量

全部内存量

集合类型

64位

100000

64位*100000 = 800KB

Bitmaps

1位

100000000

1位*100000000 = 12.5MB