上篇文章我们对STRING数据类型中的一些基本的命令进行了介绍,但是没有涉及到BIT相关的命令,本文我们就来看看几个和BIT相关的命令。
本文时Redis系列的第五篇文章,了解前面的文章有助于更好的理解本文:
Redis介绍–Linux系统下的安装(一)
Redis介绍–通用命令介绍(二)
Redis介绍–五大数据类型介绍(三)
Redis介绍–String数据类型介绍(四)
BIT相关的命令是指BITCOUNT、BITFIELD、BITOP、BITPOS、SETBIT、GETBIT几个命令,灵活使用这几个命令,可以给我们的项目带来很多惊喜。
在学习前,我们要先了解下Redis中字符串的存储方式,Redis中的字符串都是以二进制的方式进行存储的,比如以下命令:
127.0.0.1:6379> set k1 a
OK
a对应的ASCII码是97,转换为二进制数据是01100001,我们BIT相关命令都是对这个二进制数据进行操作。
GETBIT命令可以返回key对应的value在offset处的bit值,以上文提到的k1为例子,a对应的二进制数据是01100001,所以当offset为0时,对应的bit值为0;offset为1时,对应的bit值为1;offset为2时,对应的bit值为1;offset为3时,对应的bit值为0,以此类推…,如下:
127.0.0.1:6379> getbit k1 0
(integer) 0
127.0.0.1:6379> getbit k1 1
(integer) 1
127.0.0.1:6379> getbit k1 2
(integer) 1
127.0.0.1:6379> getbit k1 3
(integer) 0
127.0.0.1:6379> getbit k1 4
(integer) 0
127.0.0.1:6379> getbit k1 5
(integer) 0
127.0.0.1:6379> getbit k1 6
(integer) 0
127.0.0.1:6379> getbit k1 7
(integer) 1
SETBIT可以用来修改二进制数据,比如a对应的ASCII码为97,c对应的ASCII码为99,97转为二进制是01100001,99转为二进制是01100011,两个的差异在于第六位一个是0一个是1,通过SETBIT命令,我们可以将k1的第六的0改为1(第六位是从0开始算),如下:
127.0.0.1:6379> get k1
"a"
127.0.0.1:6379> setbit k1 6 1
(integer) 0
127.0.0.1:6379> get k1
"c"
127.0.0.1:6379>
此时,k1中存储的字符也就变成了c。SETBIT在执行时返回的数字,表示该位上原本的bit值。
BITCOUNT可以用来统计这个二进制数据中1的个数,如下:
127.0.0.1:6379> get k1
"c"
127.0.0.1:6379> bitcount k1
(integer) 4
关于BITCOUNT,Redis官网上有一个案例,用于统计用户上线次数。原文如下:
假设现在我们希望记录自己网站上的用户的上线频率,比如说,计算用户 A 上线了多少天,用户 B 上线了多少天,诸如此类,以此作为数据,从而决定让哪些用户参加 beta 测试等活动 —— 这个模式可以使用 SETBIT 和 BITCOUNT 来实现。
比如说,每当用户在某一天上线的时候,我们就使用 SETBIT ,以用户名作为 key ,将那天所代表的网站的上线日作为 offset 参数,并将这个 offset 上的为设置为 1 。
举个例子,如果今天是网站上线的第 100 天,而用户 peter 在今天阅览过网站,那么执行命令 SETBIT peter 100 1 ;如果明天 peter 也继续阅览网站,那么执行命令 SETBIT peter 101 1 ,以此类推。
当要计算 peter 总共以来的上线次数时,就使用 BITCOUNT 命令:执行 BITCOUNT peter ,得出的结果就是 peter 上线的总天数。
这种统计方式最大的好处就是节省空间并且运算速度快。每天占用一个bit,一年也就365个bit,10年也就是10*365个bit,也就是456个字节,对于这么大的数据,bit的操作速度非常快。
BITOP可以对一个或者多个二进制位串执行并(AND)、或(OR)、异或(XOR)以及非(NOT)运算,如下:a对应的ASCII码转为二进制是01100001,c对应的二进制位串是01100011。对这两个二进制位串分别执行AND、OR、XOR、的结果如下:
127.0.0.1:6379> mget s1 s2
1) "a"
2) "c"
127.0.0.1:6379> bitop and s3 s1 s2
(integer) 1
127.0.0.1:6379> mget s1 s2 s3
1) "a"
2) "c"
3) "a"
127.0.0.1:6379>
127.0.0.1:6379> bitop or s3 s1 s2
(integer) 1
127.0.0.1:6379> mget s1 s2 s3
1) "a"
2) "c"
3) "c"
127.0.0.1:6379> bitop xor s3 s1 s2
(integer) 1
127.0.0.1:6379> mget s1 s2 s3
1) "a"
2) "c"
3) "\x02"
注意:BITOP执行NOT运算时,要注意参数的个数,如下:
127.0.0.1:6379> mget s1 s2 s3 s4
1) "a"
2) "c"
3) (nil)
4) (nil)
127.0.0.1:6379> bitop not s3 s1
(integer) 1
127.0.0.1:6379> mget s1 s2 s3 s4
1) "a"
2) "c"
3) "\x9e"
4) (nil)
127.0.0.1:6379>
这里会对s1的二进制位串取反,将取反结果交给s3。
BITPOS用来获取二进制位串中第一个1或者0的位置
返回一个位置,把字符串当做一个从左到右的字节数组,第一个符合条件的在位置0,其次在位置8,等等。还是以a为例01100001如下:
127.0.0.1:6379> set s1 a
OK
127.0.0.1:6379> bitpos s1 1
(integer) 1
127.0.0.1:6379> bitpos s1 0
(integer) 0
OK!!!STRING中BIT相关命令就介绍到此,如有需要的童鞋们可以参考官网文档:https://redis.io/commands。