Bitmaps

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Bitmaps 称为位图,它不是一种数据类型。网上很多视频教程把Bitmaps称为数据类型,应该是不正确的。

1、简介

Bitmaps 称为位图,它不是一种数据类型。网上很多视频教程把Bitmaps称为数据类型,应该是不正确的。Bitmaps 是Redis提供给使用者用于操作位的“数据类型”。它主要有如下的基本特性:

  • Bitmaps 不是数据类型,底层就是字符串(key-value),byte数组。我们可以使用普通的get/set直接获取和设值位图的内容,也可以通过Redis提供的位图操作getbit/setbit等将byte数组看成“位数组”来处理
  • Bitmaps 的“位数组”每个单元格只能存储0和1,数组的下标在Bitmaps中称为偏移量
  • Bitmaps设置时key不存在会自动生成一个新的字符串,如果设置的偏移量超出了现有内容的范围,就会自动将位数组进行零扩充

2 、基本操作

2.1 SETBIT key offset value

对key存储的字符串,设置或者清除指定偏移量上的位(bit),位的设置或者清除取决于value参数,0/1;当key不存在时,自动生成一个新的字符串。字符串会进行伸展确保value保存在指定的偏移量上。字符串进行伸展时,空白位置以0填充。

时间复杂度 :

O(1)

offset 范围:

0~2^32

返回值:

指定偏移量原来存储的位

案例:

使用Bitmaps来存储用户是否打卡,打卡记做1,未打卡为0,用户的id作为偏移量

假设存在10个用户,此时用户1、3、5、9、10打了卡,其他人未打卡,Bitmaps的初始化结果如下所示:

clock:20210806代表2021/08/06的打卡记录

注意事项:

正式系统中,id肯定不会是0、1、2这种,而是以某一个数组开头,比如1000000000000001、1000000000000002这个时候非常容易导致偏移量的浪费,因此我们可以考虑通过计算减去一个合适的值后再设置偏移量,如果设置的Bitmaps偏移量过大,容易造成分配内存时间过长,Redis服务器被阻塞。

2.2 GETBIT key offset

获取指定偏移量上的位(bit),当offset比字符串长度大,或者key不存在,返回0;

时间复杂度:

O(1)

返回值:

字符串值指定偏移量上的位(bit)

案例:

clock:20210806代表2021/08/06的打卡记录

2.3 BITCOUNT key [start] [end]

计算给定字符串中,被设置为1的bit位的数量。start和end参数可以指定查询的范围,可以使用负数值。-1代表最后一个字节,-2代表倒是第二个字节。

注意:start和end是字节索引,因此每增加1 代表的是增加一个字符,也就是8位,所以位的查询范围必须是8的倍数。

时间复杂度:

O(N)

返回值:

被设置为1的位的数量

案例:

clock:20210806代表2021/08/06的打卡记录,此时一共11位,前8位置3个1,后3位中2个1

bitcount clock:20210806 0 0 表示第1个字符中1的个数

bitcount clock:20210806 1 1 表示第2个字符中1的个数

bitcount clock:20210806 0 1 表示第1和第2个字符中1的个数

2.4 BITPOS key bit [start] [end]

返回第一个置为bit的二进制位的位置,默认检测整个Bitmaps,也可以通过start和end参数指定查询范围

注意:start和end是字节索引,因此每增加1 代表的是增加一个字符,也就是8位,所以位的查询范围必须是8的倍数。

时间复杂度:

O(N)

返回值:

整数回复

案例:

bitpos clock:20210806 0 表示第一个0的位置

bitpos clock:20210806 1 表示第一个1的位置

bitpos clock:20210806 1 0 0 表示第一个字符中,第一个1的位置

bitpos clock:20210806 1 1 1 表示第二个字符中,第一个1的位置

bitpos clock:20210806 1 0 1 表示第一个和第二个字符中,第一个1的位置

2.5 BITOP operation destkey key [key …]

Redis的Bitmaps提供BITOP指令来对一个或多个(除了NOT操作)二进制位的字符串key进行位元操作,操作的结果保存到destkey上,operation是操作类型,有四种分别是:AND、OR、NOT、XOR

  • BITOP AND destkey key [key ...] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey
  • BITOP OR destkey key [key ...] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey
  • BITOP XOR destkey key [key ...] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey
  • BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey

当字符串长度不一致是,较短的那个字符串所缺失的部分会被看作0,空的key也会被看作是包含0的字符串序列

时间复杂度:

O(N)

返回值:

位运算的结果(保存到destkey的字符串的长度和输入key中的最长的字符串的长度相等)

案例:

这里使用key1 1001和key2 1011进行上述四种操作


BITOP AND destkey key [key ...]

运算规则:0&0=0;   0&1=0;    1&0=0;     1&1=1;      

即:两位同时为“1”,结果才为“1”,否则为0

BITOP OR destkey key [key ...]

运算规则:0|0=0;   0|1=1;   1|0=1;    1|1=1;   

即 :参加运算的两个对象只要有一个为1,其值为1

BITOP XOR destkey key [key ...]

运算规则:0^0=0;   0^1=1;   1^0=1;   1^1=0;  

即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0

BITOP NOT destkey key

运算规则:取反


2.6 BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]

2.1和2.2中的setbit和getbit都是对指定key的单个位的操作,如果需要对多个位同时操作,那么可以使用bitfield指令,bitfield有三个子指令,分别是get、set、incrby,它们可以对指定的片段进行读写,但是最多处理64个连续的位,超过64个连续的位,需要使用多个子指令,bitfield可以同时执行多个子指令(无符号整数只能返回63位)。


注意:

  • 使用 GET 子命令对超出字符串当前范围的二进制位进行访问(包括键不存在的情况), 超出部分的二进制位的值将被当做是 0 。
  • 使用 SET 子命令或者 INCRBY 子命令对超出字符串当前范围的二进制位进行访问将导致字符串被扩大, 被扩大的部分会使用值为 0 的二进制位进行填充。 在对字符串进行扩展时, 命令会根据字符串目前已有的最远端二进制位, 计算出执行操作所需的最小长度。

值操作子指令:

  • GET <type> <offset> —— 返回指定的二进制位范围
  • SET <type> <offset> <value> —— 对指定的二进制位范围进行设置,并返回它的旧值
  • INCRBY <type> <offset> <increment> —— 对指定的二进制位范围执行加法操作,并返回它的旧值。用户可以通过向 increment 参数传入负值来实现相应的减法操作

溢出策略子指令:

  • WRAP:回绕/折返(wrap around)-默认溢出策略,对于无符号整数来说, 回绕就像使用数值本身与能够被储存的最大无符号整数执行取模计算, 这也是 C 语言的标准行为。 对于有符号整数来说, 上溢将导致数字重新从最小的负数开始计算, 而下溢将导致数字重新从最大的正数开始计算。
  • SAT:饱和计算(saturation arithmetic),也可以理解为饱和截断,这种模式下下溢计算的结果为最小的整数值, 而上溢计算的结果为最大的整数值
  • FAIL:失败不执行,这种模式会拒绝执行那些导致上溢或者下溢的计算情况,返回nil表示计算未被执行。

需要注意的是, OVERFLOW 子命令只会对紧随着它之后被执行的 INCRBY 命令产生效果, 这一效果将一直持续到与它一同被执行的下一个 OVERFLOW 命令为止。 在默认情况下, INCRBY 命令使用 WRAP 方式来处理溢出计算。

i与u:

i表示有符号整数,u表示无符号整数。u4代表4位长的无符号整数,i8代表8位长的有符号整数。

案例:

测试数字为10100111

bitfield key get u4 0 从第一个位开始取4个位,得到无符号数1010=10

bitfield key set u8 0 128 从第0个开始,将接下来的8位用无符号整数128替换,也就是10000000

bitfield key incrby u4 2 1 从第2位开始对接下来的4位无符号数+1

bitfield key set u8 0 128  get u4 0  incrby u4 2 1 复合指令,是上面三者的组成,返回值是每个操作的子集,相当于管道操作

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6月前
|
存储 数据处理 C++
哈希的应用--位图和布隆过滤器(上)
位图 1. 位图概念 位图(Bitset)是一种数据结构,用于表示一组布尔值,其中每个元素通常对应于一个位或一个二进制值,可以存储0或1。位图在计算机科学和计算机工程中经常用于各种应用,特别是
|
1月前
|
存储 NoSQL Redis
Redis新数据类型-Bitmaps
Redis新数据类型-Bitmaps
|
6月前
|
存储 算法 Linux
哈希的应用--位图和布隆过滤器(下)
布隆过滤器 在上面我们用位图很好的解决了多重整数高效查询的问题,那么我们在面对字符串时,该如何解决呢? 1. 布隆过滤器的提出 布隆过滤器(Bloom Filter)是由布隆在1970年提出的,它是一种空间效率高、查询速度快的数据结构,主要用于判断一个元素是否属于一个集合。布隆过滤器的提出解决了在大规模数据集中进行
|
2月前
|
存储 Serverless
位图和布隆过滤器
位图和布隆过滤器
|
3月前
|
存储 算法 搜索推荐
位图与布隆过滤器
位图与布隆过滤器
46 0
|
4月前
|
存储 算法 Linux
C++ 哈希的应用【位图】
C++ 哈希的应用【位图】
28 0
|
5月前
|
存储 机器学习/深度学习 算法
C++位图和布隆过滤器
C++位图和布隆过滤器
|
8月前
|
存储 C++ 容器
哈希的应用——位图
所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的,其本质也是一种hash。但是其占用空间很少。
|
9月前
|
存储
BitSet—位图
BitSet—位图
|
存储 SQL 算法
【C++】位图 | 布隆过滤器(下)
【C++】位图 | 布隆过滤器(下)
【C++】位图 | 布隆过滤器(下)