【Redis】Redis位图(bitmap)介绍和在签到场景的应用

一、前言

基本原理:

《Redis设计与实现》中对位图的实现描述是:Redis使用字符串对象来表示位数组,因为字符串对象使用的SDS数据结构是二进制安全的,所以程序可以直接使用SDS结构来保存位数组,并使用SDS结构的操作函数来处理为数组。

所以位图本质上结构就是redis的字符串类型SDS(simple dynamic string)。
在这里插入图片描述

计算机的存储,都是以二进制0和1存储的数据,位图就是直接对数据的比特位进行读取、赋值等操作。

二、redis位图相关指令

setbit命令

  • 指令: SETBIT key offset value
  • 复杂度: O(1)
  • 含义:设置或者清空key的value(字符串)在offset处的bit值(只能只0或者1)。offset位负数或者浮点数,执行报错。(set the original bit value stored at offset)getbit命令

getbit命令

  • 指令: getbit key offset
  • 复杂度: O(1)
  • 含义:获取key的value(字符串)在offset处的bit值(只能只0或者1)。(get the bit value stored at offset.)

bitcount命令

  • 指令: bitcount key
  • 复杂度: O(N)
  • 含义:获取key的value(字符串)所有比特位设置位1的总个数(The number of bits set to 1)。

bitfield命令

  • 指令: bitfield key [option1] [option2] …
  • 复杂度: O(1) * 每个指定的子命令
  • 含义: 操作多字节位域,它会执行一系列操作,并返回一个响应数组,在参数列表中每个响应数组匹配相应的操作。
  • 官方文档: http://www.redis.cn/commands/bitfield.html

bitpos命令

  • 指令: bitpos key 0|1
  • 复杂度: O(N)
  • 含义: 命令返回字符串里面第一个被设置为1或者0的bit位。(后面还可以接start end两个参数,但是偏移量的单位是字节,不是比特位,几乎没用)

bitop命令

  • 指令:BITOP [AND|OR|NOT|XOR ]destkey key1 key2
  • 复杂度: O(N)
  • 含义: 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
  • 官方文档: http://www.redis.cn/commands/bitop.html

空间占用&第一次分配空间需要的时间
空间占用量随着偏移量的增大而增大,在redis4.0版本可使用memory usage [key] 查看key的空间占用情况。
在这里插入图片描述

官方文档数据
offset为2^32-1(分配512MB)需要~300ms
offset为2^30-1(分配128MB)需要~80ms
offset为2^28-1(分配32MB)需要~30ms
offset为2^26-1(分配8MB)需要8ms
大概的空间占用计算公式是:($offset/8/1024/1024)MB

三、应用场景

  • 签到是一个很典型的位图使用场景
  • 指令应用简介
  • getbit 查看签到状态
  • setbit 标记签到
  • bitcount 累计签到次数
  • bitfield 批量查询签到标记

下面是签到应用场景演示,如果签到后还需要有一些用户奖励领取的逻辑,当然还可能涉及到补签等用户行为,则可以利用两个比特位来实现逻辑。

累计签到应用场景

在这里插入图片描述
在这里插入图片描述

连续签到应用场景

在这里插入图片描述
在这里插入图片描述

日期签到场景

在这里插入图片描述

在这里插入图片描述

应用详情

getbit查看第n比特位值----“第N个比特位”标识“第几天的签到状态”
指令示例截图:
在这里插入图片描述

含义:
查看key为 Test4SignMzy 的value值,第一位比特位是0
需求运用:
key可以作为签到活动的某个周期, “第N个比特位”标识“第几天的签到状态”。
setbit将第n比特位标记成0或1----用户“第n天签到”就将“第n个比特位”标记为1
指令示例截图:
在这里插入图片描述

含义:

将key为 Test4SignMzy 的value值,第一位比特位赋值为1,然后查看到比特位以改变为1。

需求运用:
key可以作为签到活动的某个周期,用户“第n天签到”就将这个redis key对应value值的“第n个比特位”标记为1。
bitcount统计所有比特位中为1的个数----用户“累计签到N次”用该值查询
指令示例截图:

含义:

key为 Test4SignMzy 的value值,所占用的所有比特位中,比特位值为1的总数是4个。

需求运用:
key可以作为签到活动的某个周期,用户“累计签到N次”,就可以用value值一共有多少个比特位为1得知。
bitfield 命令可以在一次调用中同时对多个位范围进行操作
指令示例截图:
在这里插入图片描述

含义:

第一个执行“bitfield Test4SignMzy get u1 1 get u1 2 get u1 3 get u1 4 get u1 8 get u1 9 get u1 10 get u1 99”,意思就是查看Test4SignMzy对应的value的第1、2、3、4、8、9、10、99比特位的值,得到的值当作无符号1位整数返回。加入原本不存在第99位,返回0代替。 

第二个执行“bitfield Test4SignMzy get u1 #1 get u1 #2 get u1 #3 get u1 #4 get u1 #8 get u1 #9 get u1 #10 get u1 #99”,意思和第一个执行含义一样,只不过“get u1 N”中第三个参数“N”表示从这个key的value值的第0位开始,往后偏移N位比特位;而“get u1 #N”中第三个参数“#N”表示从这个key的value值的第0位开始,往后偏移“N乘1(第二个参数表示的长度)”位比特位。 

需求运用:
可以查看一个用户连续几天,或者一个周期内所有天的签到状态,由此可以得到连续目前连续签到多少天,周期内最大连续签到多少天。

猜你喜欢

转载自blog.csdn.net/u011397981/article/details/130691026