redis中bitmap 位图详解和使用场景说明 redis集群key指定节点
redis的特殊类型bitmap 的使用方式和使用场景。bitmap命令bitmap 求交集 并集
目录
目录
引言:
大家都知道redis的五种常用类型string、hash、list、set、zset 那除此之外,redis还有一些特殊类型,bitmap就属于其中一种,接下来就对bitmap做一下详细说明。
bimap介绍:
位图不是实际的数据类型,而是在字符串类型上定义的一组面向位的操作。因为字符串是二进制安全的blob,它们的最大长度为512 MB,所以可以设置2^32个不同的位。
优点:
位图可以节省大量的空间,8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。假设需要统计用户的数量,那么只需要512M的空间就可以记录40多亿用户。
基本语法:
# 将sign的第100位图设置为1
127.0.0.1:6379> setbit sign 100 1
(integer) 0
# 将sign的第200位图设置为1
127.0.0.1:6379> setbit sign 200 1
(integer) 0
#获取sign位图1的值
127.0.0.1:6379> getbit sign 1
(integer) 0
#获取sign位图100的值
127.0.0.1:6379> getbit sign 100
(integer) 1
#获取sign中位图值为1的数量
127.0.0.1:6379> bitcount sign
(integer) 2
注:因为bitmap本身意义上是在字符串类型上定义的一组面向位的操作,所以字符串类型的数据也是使用bitmap的语法
案例:
#字符串中赋值
127.0.0.1:6379> set stringa abc
OK
#获取字符串中比特位为1的个数
127.0.0.1:6379> bitcount stringa
(integer) 10
BITOP用法
BITOP operation destkey key [key ...] 作用:对一个或多个保存二进制位的字符串 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
。
案例说明:
# 分别给signa signb填充数据
127.0.0.1:6379> setbit signa 1 1
(integer) 0
127.0.0.1:6379> setbit signa 2 1
(integer) 0
127.0.0.1:6379> setbit signa 3 1
(integer) 0
127.0.0.1:6379> setbit signa 4 1
(integer) 0
127.0.0.1:6379> setbit signb 4 1
(integer) 0
127.0.0.1:6379> setbit signb 5 1
(integer) 0
127.0.0.1:6379> setbit signb 6 1
(integer) 0
#查看signa signb数量
127.0.0.1:6379> bitcount signa
(integer) 4
127.0.0.1:6379> bitcount signb
(integer) 3
#求signa与signb的交集并赋值在signc中
127.0.0.1:6379> bitop and signc signa signb
(integer) 1
127.0.0.1:6379> bitcount signc
(integer) 1
#求signa与signb的并集并赋值在signd中
127.0.0.1:6379> bitop or signd signa signb
(integer) 1
127.0.0.1:6379> bitcount signd
(integer) 6
#求signa与signb的差集(在signa中存在signb中不存在和signb中存在,signa中不存在的)并赋值在signf中,
127.0.0.1:6379> bitop xor signf signa signb
(integer) 1
127.0.0.1:6379> bitcount signf
(integer) 5
#给signaa赋值
127.0.0.1:6379> setbit signaa 1 1
(integer) 0
#将signaa取非存放到signnot中,因signaa只有第一位图为1,其余7个位图为0,取非的话就会有7个位图为1,所以signnot求bitcount为7
127.0.0.1:6379> bitop not signnot signaa
(integer) 1
127.0.0.1:6379> bitcount signnot
(integer) 7
127.0.0.1:6379> del signnot
(integer) 1
127.0.0.1:6379> setbit signaa 7 1
(integer) 0
127.0.0.1:6379> bitop not signnot signaa
(integer) 1
127.0.0.1:6379> bitcount signnot
(integer) 6
#因signaa第10个比特位占用两个字节,故共用16个比特位,其中为1的有3个位图,取非后bitcount为13
127.0.0.1:6379> setbit signaa 10 1
(integer) 0
127.0.0.1:6379> bitop not signnot signaa
(integer) 2
127.0.0.1:6379> bitcount signnot
(integer) 13
注:redis是支持多分片的,若两个key存在不同的节点上,无法实现求交集、并集之类的操作。
redis集群指定节点
Redis 集群中内置了 16384 个哈希槽,当我们存储一个key时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
如果redis集群有三个节点
redis节点1,负责存储5461个哈希槽的数据,编号0号至5460号哈希槽
redis节点2,负责存储5462个哈希槽的数据,编号5461号至10922号哈希槽
redis节点3,负责存储5461个哈希槽的数据,编号10923号至16383号哈希槽
当我们存储不同的bitmap时,计算出哈希槽后可能会分配在不同的节点,不同节点之间是无法做运算的,这个时候我们就可以将不同的key指定同一节点存储。
HashTag机制可以影响key被分配到的slot(哈希槽),从而可以使用那些被限制在slot中操作。
HashTag即是用{}包裹key的一个子串,如{user:}1, {user:}2。
在设置了HashTag的情况下,集群会根据HashTag决定key分配到的slot, 两个key拥有相同的HashTag:{user:}, 它们会被分配到同一个slot,允许我们使用MGET命令。
通常情况下,HashTag不支持嵌套,即将第一个{和第一个}中间的内容作为HashTag。若花括号中不包含任何内容则会对整个key进行散列,如{}user:。
使用场景
1、统计当日、每天有多少用户登录
根据日期,每天对应一个key。用户登录时将用户存到对应位图中,采用bitcount即可获取当日登录用户数。
2、统计最近7天连续登录的用户数
根据日期,每天对应一个key。若想知道最近7天连续登录的用户个数,获取7天对应的bitmap的key,进行求交集。
3、统计7天共有多少用户登录
方案1:根据日期,每天对应一个key。若想知道最近7天登录的用户个数,获取当月对应的bitmap的key,进行求并集。
方案2:若想统计的某月共多少用户登录,存储的时候可按月份设置相应key,具体实现方式根据需求决定。
更多推荐
所有评论(0)