Redis——》数据类型:bitmap

推荐链接:
    总结——》【Java】
    总结——》【Mysql】
    总结——》【Redis】
    总结——》【Spring】
    总结——》【SpringBoot】
    总结——》【MyBatis、MyBatis-Plus】


相关链接:
    Redis——》数据类型
    Redis——》数据类型:string(字符串)
    Redis——》数据类型:hash(哈希)
    Redis——》数据类型:list(列表)
    Redis——》数据类型:set(集合)
    Redis——》数据类型:zset(有序集合)
    Redis——》数据类型:bitmap

Redis——》数据类型:bitmap

  • 一、底层结构
  • 二、最大长度
  • 三、操作示例
    • 1、setbit:设置二进制位的值
    • 2、getbit:获取二进制位的值
    • 3、bitcount:统计二进制位为1的数量
    • 4、bitops:查找第一个指定的二进制位值
    • 5、bitop:位操作
    • 6、bitfield:在位图中存储整数值
  • 四、使用场景
    • 1、记录用户登录状态
    • 2、统计用户登录天数
    • 3、统计用户每个月的签到情况
    • 4、统计连续签到用户总数

一、底层结构

由多个二进制位组成的数组,数组中的每个二进制位都有与之对应的偏移量(也称索引),用户通过这些偏移量可以对位图中指定的一个或多个二进制位进行操作。

二、最大长度

512Mb = 512 * 1024 * 1024 * 8 = 2^32

三、操作示例

命令 帮助 语法 描述
setbit help setbit setbit key offset value 设置二进制位的值
getbit help getbit getbit key offset 获取二进制位的值
bitcount help bitcount bitcount key [start end] 统计二进制位为1的数量
bitops help bitops bitpos key bit [start] [end] 查找第一个指定的二进制位值
bitop help bitop 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
bitfield 在位图中存储整数值

1、setbit:设置二进制位的值

注意:
(1)如果设置某个偏移量超出了现有的内容范围,位数组就会自动扩充。
因为Redis对位图的扩展操作是以字节为单位进行的,所以扩展之后的位图包含的二进制位数量可能会比用户要求多一些,并且在扩展位图的同时,Redis还会将所有未被设置的二进制位的值初始化为0。
(2)setbit命令只能使用正数偏移量,输入负数会报错

setbit key offset value

# 底层的二进制:10000000
setbit k1 0 1

# 底层存储的二进制:10010000
setbit k1 3 1

# 底层存储的二进制:10010100
setbit k1 5 1

# 底层存储的二进制:10010100 01000000
setbit k1 9 1

Redis——》数据类型:bitmap_第1张图片

2、getbit:获取二进制位的值

注意:
如果输入的偏移量超过了位图目前拥有的最大偏移量,那么getbit命令将返回0

getbit key offset

getbit k1 0
getbit k1 3
getbit k1 5
getbit k1 7
getbit k1 111

Redis——》数据类型:bitmap_第2张图片

3、bitcount:统计二进制位为1的数量

注意:
(1)默认对所有字节中的二进制位进行统计
(2)start、end对指定字节范围内的二进制位进行统计(正向字节偏移量从0开始,反向从-1开始)

bitcount key [start end]

命令 描述
bitcount k1 在所有字节中,统计二进制位为1的数量
bitcount k1 0 -1 在所有字节中,统计二进制位为1的数量
bitcount k1 0 0 在第1个字节中,统计二进制位为1的数量
bitcount k1 1 1 在第2个字节中,统计二进制位为1的数量
bitcount k1 -1 -1 在最后1个字节中,统计二进制位为1的数量
bitcount k1 -2 -2 在倒数第2个字节中,统计二进制位为1的数量
bitcount k1 0 1 在前2个字节中,统计二进制位为1的数量
bitcount k1 -2 -1 在后2个字节中,统计二进制位为1的数量

Redis——》数据类型:bitmap_第3张图片

4、bitops:查找第一个指定的二进制位值

注意:
(1)默认对所有字节中查找第一个指定的二进制位值
(2)start、end对指定字节范围内查找第一个指定的二进制位值(正向字节偏移量从0开始,反向从-1开始)
(3)对一个不存在的位图或者一个所有位都被设置成0的位图中查找值为1的二进制位时,BITPOS命令将返回-1

bitpos key bit [start] [end]

命令 描述
bitpos k1 0 在所有字节中,查找第1个为0的位偏移量
bitpos k1 1 在所有字节中,查找第1个为1的位偏移量
bitpos k1 1 0 -1 在所有字节中,查找第1个为1的位偏移量
bitpos k1 1 0 0 在第1个字节中,查找第1个为1的位偏移量
bitpos k1 1 1 1 在第2个字节中,查找第1个为1的位偏移量
bitpos k1 1 -1 -1 在最后1个字节中,查找第1个为1的位偏移量
bitpos k1 1 -2 -2 在倒数第2个字节中,查找第1个被设置为1的位偏移量
bitpos k1 1 0 1 在前2个字节中,查找第1个被设置为1的位偏移量
bitpos k1 1 -2 -1 在后2个字节中,查找第1个被设置为1的位偏移量

Redis——》数据类型:bitmap_第4张图片

5、bitop:位操作

注意:
当BITOP命令在对两个长度不同的位图执行运算时,会将长度较短的那个位图中不存在的二进制位的值看作0。

命令 描述
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
# bitmap1:01010011
# bitmap2:1001010010010101

bitop and and_result bitmap1 bitmap2
bitop or or_result bitmap1 bitmap2
bitop xor xor_result bitmap1 bitmap2
bitop not not_result bitmap1

Redis——》数据类型:bitmap_第5张图片

6、bitfield:在位图中存储整数值

四、使用场景

# 设置二进制位的值
setbit key offset value

# 获取二进制位的值
getbit key offset

# 统计二制位为1的数量
bitcount key [start end]

# 查找第一个指定的二进制位值
bitpos key bit [start] [end]

# 对一个或多个 key 求逻辑并,并将结果保存到 destkey 
bitop and destkey key [key …]	

1、记录用户登录状态

以下属于同一类场景:

  • 记录用户登录状态
  • 记录用户打卡状态
  • 记录用户参与活动状态
假设用户ID为10086

思路:
	key		:存储用户登陆状态集合数据,当前为user:login:status
	offset	:存储用户ID,当前为10086
	value	:存储登录状态(在线为1,下线为0)

# 记录用户登录
setbit user:login:status 10086 1

# 记录用户登出
setbit user:login:status 10086 0

# 判断用户是否登录(在线为1,下线为0)
getbit user:login:status 10086

2、统计用户登录天数

一年最多366天 = 366个二进制位 = 45.75个字节 ≈ 46个字节

假设用户ID为10086

思路:
	key		:存储用户登陆状态集合数据,当前为user:login:10086
	offset:存储天数-1
	value	:存储登录状态(在线为1,下线为0)

# 记录用户第2天登录
setbit user:login:10086 1 1

# 记录用户第8天登录
set user:login:10086 7 1

# 记录用户第365天登录
set user:login:10086 364 1

# 字节长度:46
strlen sean

# 统计用户登录天数
bitcount user:login:10086

# 统计用户最后2周登录天数,结果:1
bitcount user:login:10086 -2 -1

3、统计用户每个月的签到情况

假设用户ID为10086,当前日期为2022年11月29日

思路:
	key		:存储用户每月每天签到状态集合数据,当前为user:sign:{userId}:{yyyyMM}
	offset	:存储对应日期-1(因为offset从0开始)
	value	:存储签到状态(签到为1,未签到为0)


# 记录用户2022年11月29日签到
setbit user:sign:10086:202211 28 1

# 判断用户2022年11月29日是否签到
getbit user:sign:10086:202211 28

# 统计用户2022年11月签到次数
bitcount user:sign:10086:202211

# 查找用户2022年11月首次签到日期(因为offset从0开始,所以日期值=offset+1)
bitpos user:sign:10086:202211 1

4、统计连续签到用户总数

假设从2022年11月27日到2022年11月29日,如何统计出这3天连续打卡用户总数?

思路:
	(1)3天对应3个Bitmap,并且offset上的userID都是一样的。
	(2)3个Bitmap做『并』运算(如果offset上的值都为1,则说明这个用户3天连续打卡)。
	(3)把『并』结果保存到一个新 Bitmap 中,统计 bit = 1 的个数便得到了连续打卡 3 天的用户总数了。


# 记录2022年11月27日用户签到
setbit user:sign:20221127 10086 1
setbit user:sign:20221127 10087 1
setbit user:sign:20221127 10088 1
setbit user:sign:20221127 10089 1


# 记录2022年11月28日用户签到
setbit user:sign:20221128 10087 1
setbit user:sign:20221128 10088 1
setbit user:sign:20221128 10089 1


# 记录2022年11月29日用户签到
setbit user:sign:20221129 10088 1
setbit user:sign:20221129 10089 1

# 与操作
bitop and destkey user:sign:20221127 user:sign:20221128 user:sign:20221129

# 统计 bit 位 = 1 的个数
bitcount destkey 1

Redis——》数据类型:bitmap_第6张图片

你可能感兴趣的:(Redis,redis,bitmap,位,二进制)