【重学Redis】关于Bitmap的介绍

开课吧杰米粉2021-12-07 14:58

  Bitmap不是实际的数据类型,而是在字符串类型上定义的一组面向位的操作(对string类型封装的一组命令)。字符串是二进制安全的,其最大长度为512 MB,可以设置2^32个不同的位。

  位图的最大优点之一是,在存储信息时,通常可以极大地节省空间。例如,在一个系统中,不同的用户由增量用户ID表示,仅使用512MB内存就可以记住40亿用户的一位信息(例如,存储用户是否需要接收通知)。

  Bitmap的结构

  Bitmap的本质其实是一个字节数组,每个元素只能存储0、1两个值。

  setbit:如果key不存在创建一个bitmap,并且在对应的位置(offset)设置对应的值(0或者1),没有set的位置默认值为0

  getbit:取对应位置的值。

  bitcount:统计数组中一共有多少个1

【重学Redis】我:Bitmap最大占用512M内存,面试官:你确定?

  Bitmap的扩容

  在这里,我们用必要重新学习一下空间的换算关系

  1Byte(字节)=8bit(位)

  1 KB = 1024 Byte

  1 MB = 1024 KB

  1 GB = 1024 MB

  1TB = 1024GB

  当我们设置offset为7以内的元素时,由于1字节是8个bit,所以我们的操作范围局限于1字节以内,STRLEN得到的长度也是1

127.0.0.1:6379> setbit bitkey 0 1
(integer) 0
127.0.0.1:6379> BITCOUNT bitkey
(integer) 1
127.0.0.1:6379> STRLEN bitkey
(integer) 1
127.0.0.1:6379> setbit bitkey 7 1
(integer) 0
127.0.0.1:6379> BITCOUNT bitkey
(integer) 2
127.0.0.1:6379> STRLEN bitkey
(integer) 1

  当我们设置offset超过7的元素时,就会根据offset/8+1进行扩容

127.0.0.1:6379> setbit bitkey 8 1
(integer) 0
127.0.0.1:6379> BITCOUNT bitkey
(integer) 3
127.0.0.1:6379> STRLEN bitkey
(integer) 2
127.0.0.1:6379> setbit bitkey 800 1
(integer) 0
127.0.0.1:6379> STRLEN bitkey
(integer) 101

  当设置最后一个可能的位(offset等于2^32-1)时,Redis需要分配这个键所需的全部内存,这些内存可能会阻塞服务器一段时间。在2010 MacBook Pro上,设置offset为2^32-1(512MB分配)需要约300ms,设置offset为2^30-1(128MB分配)需要约80ms,设置offset为2^28-1(32MB分配)需要约30ms,设置offset为2^26-1(8MB分配)需要约8ms。请注意,完成第一次分配后,后续调用将不会产生分配开销。

  Bitmap的最大大小

  在上文中我们说道,bitmap的最大大小为512M,为什么呢?

  因为Bitmap的数据结构还是String,只是封装了一组新的针对string的命令而已,string的最大大小是512M,所以,Bitmap的大小是受到string的大小限制

  可能你又要问了,为什么String的最大大小是512M呢?

  如果我说“官网是这么说的”,那你可能会打si我,我还是告诉你吧

  在redis的配置文件里,有一个配置参数为proto_max_bulk_len,这个参数的默认值是512M,但是可以设置的更大一点

#修改redis的配置文件redis.conf
proto-max-bulk-len 1024mb
#重启redis
./bin/redis-cli shutdown
./bin/redis-server redis.conf
#测试
127.0.0.1:6379> setbit bitkey 4294967296 1
(integer) 0
(0.93s)
127.0.0.1:6379> STRLEN bitkey
(integer) 536870913
127.0.0.1:6379> setbit bitkey 8589934591 1
(integer) 0
(2.21s)
127.0.0.1:6379> setbit bitkey 8589934592 1
(error) ERR bit offset is not an integer or out of range

  可以发现,我们通过修改配置文件,是可以改变Bitmap的最大内存的,其实也就是改变了string的最大内存,新的最大的offset已经变成了2^33-1.最大容量变成了我们更改的1024MB,原理咱们留到String的源码的时候再为大家详细解读

  官网说明

  在官网中,Bitmap的最大大小是512M

  One of the biggest advantages of bitmaps is that they often provide extreme space savings when storing information. For example in a system where different users are represented by incremental user IDs, it is possible to remember a single bit information (for example, knowing whether a user wants to receive a newsletter) of 4 billion of users using just 512 MB of memory.

  String的最大大小也是512M

  Values can be strings (including binary data) of every kind, for instance you can store a jpeg image inside a value. A value can't be bigger than 512 MB.

  应用

  咱们首先进行一组计算

setbit login:20211203 uid-n 1

  假如我们的系统uid是以n为开头顺序递增,我们可以把uid-n的作为offset,今天是否登陆为值,我们通过

bitcount login:20211203

  把用户的登陆状态保存,然后通过

  bitcount login:20211203

  就可以计算出当天的日活了

  这样的话,我们一个Bitmap就可以存储4.294.967.296个用户的登陆信息,而且只用花费512M的内存,这样是非常划算的

  redis的应用场景非常广泛,这里只是一个引子,后续咱们会详细介绍redis的上百种实战场景,希望大家跟着我一起进步

  以上就是开课吧小编为大家整理发布的“【重学Redis】关于Bitmap的介绍”一文,更多相关内容尽在开课吧广场Java教程频道。

【重学Redis】我:Bitmap最大占用512M内存,面试官:你确定?

免责声明:本站所提供的内容均来源于网友提供或网络搜集,由本站编辑整理,仅供个人研究、交流学习使用。如涉及版权问题,请联系本站管理员予以更改或删除。
有用
分享