目录

目录

引言:

bimap介绍:

优点:

基本语法:

BITOP用法

redis集群指定节点

使用场景

1、统计当日、每天有多少用户登录

2、统计最近7天连续登录的用户数

3、统计7天共有多少用户登录



引言:

大家都知道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,具体实现方式根据需求决定。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐