当前位置:   article > 正文

Redis实战 - 08 Redis 的 BitMaps 位图命令

Redis实战 - 08 Redis 的 BitMaps 位图命令


现代计算机用二进制位作为信息的基础单位,1个字节等位8位,例如 big 字符串是由3个字节组成,但实际在计算机存储时将其用二进制表示,big 分别对应的ASCII码分别是98、105、103,对应的二进制分别是01100010、01101001和01100111,如下图:

在这里插入图片描述

Bitmaps本身不是一种数据类型, 实际上它就是字符串,但是它可以对字符串的位进行操作。可以把 Bitmaps 想象成一个以位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmaps 中叫做偏移量。

在这里插入图片描述

合理地使用位能够有效地提高内存使用率和开发效率,很适合用于签到这类场景。比如按月进行存储,一个月最多31天,那么我们将该月用户的签到缓存二进制就是 00000000000000000000000000000000,当某天签到将0改成1即可,而且 Redis 提供 对bitmap 的很多操作比如存储、获取、统计等指令,使用起来非常方便。

1. getbit key offset

在这里插入图片描述

获取位图指定索引的值:

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set hello big
OK
127.0.0.1:6379> getbit hello 0
(integer) 0
127.0.0.1:6379> getbit hello 15
(integer) 1
127.0.0.1:6379> getbit hello 10
(integer) 1
127.0.0.1:6379> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2. setbit key offset value

在这里插入图片描述

给位图指定索引设置值,返回该索引位置的原始值:

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set hello big
OK
127.0.0.1:6379> getbit hello 7
(integer) 0
127.0.0.1:6379> setbit hello 7 1
(integer) 0
127.0.0.1:6379> getbit hello 7
(integer) 1
127.0.0.1:6379> get hello
"cig"
127.0.0.1:6379>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3. bitcount key [start end]

获取位图指定范围(start到end,单位为字节,如果不指定就是获取全部)位值为1的个数:

在这里插入图片描述

默认情况下整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。start、end 是指 bit 组的字节的下标数,二者皆包含。

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set hello big
OK
127.0.0.1:6379> bitcount hello
(integer) 12
127.0.0.1:6379> getbit hello 7
(integer) 0
127.0.0.1:6379> setbit hello 7 1
(integer) 0
127.0.0.1:6379> bitcount hello 
(integer) 13
127.0.0.1:6379> bitcount hello 0 1
(integer) 8
127.0.0.1:6379> bitcount hello 0 2
(integer) 13
127.0.0.1:6379> bitcount hello 1 1
(integer) 4
127.0.0.1:6379> bitcount hello 1 2
(integer) 9
127.0.0.1:6379> bitcount hello 2 2
(integer) 5
127.0.0.1:6379> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

4. bitop and|or|not|xor destkey key [key…]

做多个bitmap的and(交集)、or(并集)、not(非)、xor(异或)操作并将结果保存到 destkey 中:

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set hello big
OK
127.0.0.1:6379> set world big
OK
127.0.0.1:6379> bitop and destkey hello world
(integer) 3
127.0.0.1:6379> bitop or destkey hello world
(integer) 3
127.0.0.1:6379> get destkey
"big"
127.0.0.1:6379> bitop not destkey hello
(integer) 3
127.0.0.1:6379> get destkey
"\x9d\x96\x98"
127.0.0.1:6379> bitop xor destkey hello world
(integer) 3
127.0.0.1:6379> get destkey
"\x00\x00\x00"
127.0.0.1:6379>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

5. bitpos key bit [start] [end]

返回字符串里面第一个被设置为1或者0的bit位:

在这里插入图片描述

默认情况下整个字符串都会被检索一次,只有在指定start和end参数(指定start和end位是可行的),该范围被解释为一个字节的范围,而不是一系列的位。所以start=0 并且 end=2是指前三个字节范围内查找。

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set hello big
OK
127.0.0.1:6379> bitpos hello 1
(integer) 1
# 查找字符串里面bit值为0的位置
127.0.0.1:6379> bitpos hello 0
(integer) 0
# 从第1个字节开始的位置,查找字符串里面bit值为0的位置
127.0.0.1:6379> bitpos hello 0 1
(integer) 8
# 第2个字节开始的位置,查找字符串里面bit值为1的位置 
127.0.0.1:6379> bitpos hello 1 2
(integer) 17
# 第0个字节开始到第1个字节结束的位置,查找字符串里面bit值为1的位置
127.0.0.1:6379> bitpos hello 1 0 1
(integer) 1
127.0.0.1:6379>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

6. BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment]

BITFIELD 命令可以将一个 Redis 字符串看作是一个由二进制位组成的数组, 并对这个数组中储存的长度不同的整数进行访问 (被储存的整数无需进行对齐)。 换句话说, 通过这个命令, 用户可以执行诸如 “对偏移量 1234 上的 5 位长有符号整数进行设置”、 “获取偏移量 4567 上的 31 位长无符号整数”等操作。 此外, BITFIELD 命令还可以对指定的整数执行加法操作和减法操作, 并且这些操作可以通过设置妥善地处理计算时出现的溢出情况。

BITFIELD 命令可以在一次调用中同时对多个位范围进行操作: 它接受一系列待执行的操作作为参数, 并返回一个数组作为回复, 数组中的每个元素就是对应操作的执行结果。

一次对多个位范围进行操作。bitfield 有三个子指令,分别是 get/set/incrby。每个指令都可以对指定片段做操作。

在这里插入图片描述

子命令:GET —— 返回指定的二进制位范围。

bitfield key get type offset

# 类型u代表无符号十进制,i代表带符号十进制
# 从偏移量offset=0开始取3位,获取无符号整数的值(将前3位二进制011转为无符号10进制返回)
127.0.0.1:6379> bitfield hello get u3 0
1) (integer) 3
# 从偏移量offset=0开始取4位,获取无符号整数的值(将前4位二进制0110转为无符号10进制返回)
127.0.0.1:6379> bitfield hello get u4 0
1) (integer) 6
# 从偏移量offset=0开始取5位,获取无符号整数的值(将前5位二进制01100转为无符号10进制返回)
127.0.0.1:6379> bitfield hello get u5 0
1) (integer) 12
# 从偏移量offset=1开始取2位,获取无符号整数的值(11前面补0,就是0011,转为无符号10进制返回)
127.0.0.1:6379> bitfield hello get u2 1
1) (integer) 3
# 从偏移量offset=0开始取2位,获取带符号整数的值(01前面补0,就是0001,转为带符号10进制返回)
127.0.0.1:6379> bitfield hello get i2 0
1) (integer) 1
127.0.0.1:6379> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

子命令:SET —— 对指定的二进制位范围进行设置,并返回它的旧值。

bitfield key set type offset value

# 从偏移量offset=0开始取3位,设置为无符号的整数5并返回旧值
127.0.0.1:6379> bitfield hello set u3 0 5
1) (integer) 3
127.0.0.1:6379> bitfield hello get u3 0
1) (integer) 5
# 从偏移量offset=0开始取4位,设置为无符号的整数6并返回旧值
127.0.0.1:6379> bitfield hello set u4 0 6
1) (integer) 10
127.0.0.1:6379> bitfield hello get u4 0
1) (integer) 6
# 从偏移量offset=0开始取4位,设置为带符号的整数5并返回旧值
127.0.0.1:6379> bitfield hello set i4 0 5
1) (integer) 6
127.0.0.1:6379> bitfield hello get i4 0
1) (integer) 5

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

子命令:INCRBY —— 对指定的二进制位范围执行加法操作,并返回它的旧值。用户可以通过向 increment 参数传入负值来实现相应的减法操作。

bitfield key incrby type offset increment

# 从偏移量offset=0开始取4位,获取无符号整数的值
# 从偏移量offset=6开始取4位,设置为无符号的整数6 
# 从偏移量offset=4开始取4位,获取无符号整数的值并自增1
127.0.0.1:6379> bitfield hello get u4 0 set u4 4 6 incrby u4 4 1
1) (integer) 5
2) (integer) 2
3) (integer) 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
# 从偏移量offset=0开始取4位,获取无符号整数的值
127.0.0.1:6379>  bitfield hello get u4 0
1) (integer) 5
# 从偏移量offset=4开始取4位,设置为无符号整数6
127.0.0.1:6379>  bitfield hello set u4 4 6
1) (integer) 7
# 从偏移量offset=4开始取4位,获取无符号整数的值并自增1
127.0.0.1:6379> bitfield hello incrby u4 4 1
1) (integer) 7
# 从偏移量offset=4开始取4位,获取无符号整数的值
127.0.0.1:6379> bitfield hello get u4 4
1) (integer) 7
# 从偏移量offset=4开始取4位,获取无符号整数的值并自增1
127.0.0.1:6379> bitfield hello get u4 4 incrby u4 4 1
1) (integer) 7
2) (integer) 8
# 从偏移量offset=0开始取4位,获取无符号整数的值
127.0.0.1:6379> bitfield hello get u4 4
1) (integer) 8
127.0.0.1:6379>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/382015
推荐阅读
相关标签
  

闽ICP备14008679号