文章目录
- 一、前言
- 二、redis位图相关指令
- setbit命令
- getbit命令
- bitcount命令
- bitfield命令
- bitpos命令
- bitop命令
- 三、应用场景
- 累计签到应用场景
- 连续签到应用场景
- 日期签到场景
- 应用详情
一、前言
基本原理:
《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(第二个参数表示的长度)”位比特位。
需求运用:
可以查看一个用户连续几天,或者一个周期内所有天的签到状态,由此可以得到连续目前连续签到多少天,周期内最大连续签到多少天。