首页 > 数据库 >Redis---bitmap位图

Redis---bitmap位图

时间:2022-08-16 00:23:16浏览次数:79  
标签:127.0 0.1 Redis --- 6379 key integer 位图 SETBIT

1.前言

在平时开发过程中,经常会有一些 bool 类型数据需要存取。比如记录用户一年内签到的次数,签了是 1,没签是 0。如果使用 key-value 来存储,那么每个用户都要记录 365 次,当用户成百上亿时,需要的存储空间将非常巨大。为了解决这个问题,Redis 提供了位图结构。

位图(bitmap)同样属于 string 数据类型。Redis 中一个字符串类型的值最多能存储 512 MB 的内容,每个字符串由多个字节组成,每个字节又由 8 个 Bit 位组成。位图结构正是使用“位”来实现存储的,它通过将比特位设置为 0 或 1来达到数据存取的目的,这大大增加了 value 存储数量,它存储上限为2^32 

位图本质上就是一个普通的字节串,也就是 bytes 数组。您可以使用getbit/setbit命令来处理这个位数组,位图的结构如下所示:

位数组


位图适用于一些特定的应用场景,比如用户签到次数、或者登录次数等。上图是表示一位用户 10 天内来网站的签到次数,1 代表签到,0 代表未签到,这样可以很轻松地统计出用户的活跃程度。相比于直接使用字符串而言,位图中的每一条记录仅占用一个 bit 位,从而大大降低了内存空间使用率。

Redis 官方也做了一个实验,他们模拟了一个拥有 1 亿 2 千 8 百万用户的系统,然后使用 Redis 的位图来统计“日均用户数量”,最终所用时间的约为 50ms,且仅仅占用  16 MB内存。

2. 位图应用原理

某网站要统计一个用户一年的签到记录,若用 sring 类型存储,则需要 365 个键值对。若使用位图存储,用户签到就存 1,否则存 0。最后会生成 11010101... 这样的存储结果,其中每天的记录只占一位,一年就是 365 位,约为 46 个字节。如果只想统计用户签到的天数,那么统计 1 的个数即可。

位图操作的优势,相比于字符串而言,它不仅效率高,而且还非常的节省空间。

Redis  的位数组是自动扩展的,如果设置了某个偏移位置超出了现有的内容范围,位数组就会自动扩充。

下面设置一个名为 a 的 key,我们对这个 key 进行位图操作,使得 a 的对应的 value 变为“he”。

首先我们分别获取字符“h”和字符“e”的八位二进制码,如下所示:

>>> bin(ord("h"))
'0b1101000'
>>> bin(ord("e"))
'0b1100101'

接下来,只要对需值为 1 的位进行操作即可。如下图所示:

bitmap位图应用


把 h 和 e 的二进制码连接在一起,第一位的下标是 0,依次递增至 15,然后将数字为 1 的位置标记出来,得到 1/2/4/9/10/13/15,我们把这组数字称为位的“偏置数”,最后按照上述偏置数对字符 a 进行如下位图操作。注意,key 的初始二进制位全部为 0。

C:\Users\Administrator>redis-cli
127.0.0.1:6379> SETBIT a 1 1
(integer) 0
127.0.0.1:6379> SETBIT a 2 1
(integer) 0
127.0.0.1:6379> SETBIT a 4 1
(integer) 0
127.0.0.1:6379> get hello
"h"
127.0.0.1:6379> SETBIT a 9 1
(integer) 0
127.0.0.1:6379> SETBIT a 10 1
(integer) 0
127.0.0.1:6379> SETBIT a 13 1
(integer) 0
127.0.0.1:6379> SETBIT a 15 1
(integer) 0
127.0.0.1:6379> get hello
"he"

从上述示例可以得出,位图操作会自动对 key 进行扩容。

如果对应位的字节是不可以被打印的,那么 Redis 会以该字符的十六进制数来表示它,如下所示:

127.0.0.1:6379> SETBIT b 0 1
(integer) 0
127.0.0.1:6379> SETBIT b 1 1
(integer) 0
127.0.0.1:6379> get b
"\xc0"

3. 位图常用命令

1) SETBIT命令

用来设置或者清除某一位上的值,其返回值是原来位上存储的值。key 在初始状态下所有的位都为 0 ,语法格式如下:

SETBIT key offset value

其中 offset 表示偏移量,从 0 开始。示例如下:

127.0.0.1:6379> SET user:1 a
OK
#设置偏移量为0
127.0.0.1:6379> SETBIT user:1 0 1
(integer) 0
#当对应位的字符是不可打印字符,redis会以16进制形式显示
127.0.0.1:6379> GET user:1
"\xe1"

2) GETBIT命令

用来获取某一位上的值。示例如下:

127.0.0.1:6379> GETBIT user:1 0
(integer) 1

当偏移量 offset 比字符串的长度大,或者当 key 不存在时,返回 0。

redis> EXISTS bits
(integer) 0
redis> GETBIT bits 100000
(integer) 0

3) BITCOUNT命令

统计指定位区间上,值为 1 的个数。语法格式如下:

BITCOUNT key [start end]

示例如下:

127.0.0.1:6379> BITCOUNT user:1
(integer) 8

通过指定的 start 和 end 参数,可以让计数只在特定的字节上进行。start 和 end 参数和 GETRANGE 命令的参数类似,都可以使用负数,比如 -1 表示倒数第一个位, -2 表示倒数第二个位。

在线练习工具:https://try.redis.io/
查看更多命令:https://redis.io/commands

标签:127.0,0.1,Redis,---,6379,key,integer,位图,SETBIT
From: https://www.cnblogs.com/jiajunling/p/16590194.html

相关文章

  • Redis---数值操作命令
    1.前言Redisstring类型提供了一些专门操作数值的命令,比如INCRBY(自增)、DECRBR(自减)、INCR(加1)和DECR(减1)等命令。数值操作,同样有特定的应用场景,比如常见的点赞、取消点......
  • Git操作 :从一个分支cherry-pick多个commit到其他分支
    在branch1开发,进行多个提交,这时切换到branch2,想把之前branch1分支提交的commit都【复制】过来,怎么办?首先切换到branch1分支,然后查看提交历史记录,也可以用sourceTree查看,也......
  • go基础 - WaitGroup用法
    go基础-WaitGroup用法packagemainimport( "fmt" "sync" "time")/***CreatedbyGoland*User:[email protected]*Time:2022/8/15-23:33......
  • Elasticsearch 字段别名 field-alias
    环境Elasticsearch8.1Kibana8.1MacOS10.14.6简介首先我们还是先了解一下,什么是字段别名?大家可能听说过索引别名,通过索引的别名可以轻松的切换所需的数据来源与哪......
  • 2022-08-15 第三组 陈迪 学习笔记
    Myspl数据库:数据库:数据库【按照数据结构来组织、存储和管理数据的仓库】。是一个长期储存在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。数据对于......
  • MySql--存储过程
    MySql--存储过程创建DELIMITER$$--代表执行分隔符(原来是;这里重新定义为$$)USE`furn_ssm`$$--存储过程建立在数据库下,这里指使用数据库furn_ssmDROPPROCEDURE......
  • leetcode1282-用户分组
    用户分组哈希分类给每一个组别容量分配一个List,存入哈希表中。遍历数组,将当前下标加入对应数量的List中。如果List数量满了,那么将其从map中删除并存入返回值。class......
  • 线段树----区间问题的神
    《标准线段树》  普通的线段树,其区间一般都是一个序列的数的个数,但还是要根据不同题目来判断注意:tr[]空间是N*4,N为最大范围《单点修改,区间查询》原题:https://www.......
  • 《GB28379-2012》PDF下载
    《GB28379-2012便器冲洗阀用水效率限定值及用水效率等级》PDF下载《GB28379-2012》简介本标准规定了机械式便器冲压阀、压力式便器冲洗阀、非接触式便器冲洗阀的用水效......
  • 《GB28373-2012》PDF下载
    《GB28373-2012N类和O类罐式车辆侧倾稳定性》PDF下载《GB28373-2012》简介本标准规定了N和O类罐式车辆侧倾稳定性的术语、定义、限值要求、实车试验法、模拟计算法、......