-
对于开关 / 签到类型的业务数据,可以考虑采用
bitmap
(即位图)的数据结构进行存储 -
位图的最小单元是
bit
,每个 bit 的取值只能是 0 或 1,如下图所示:
-
Redis 字符位顺序与其 ASCII 码二进制值位顺序相反,多个字符会自动扩容连接在一起:
-
set
整存,get
整取,setbit
零存,getbit
零取:127.0.0.1:6379> set w he 127.0.0.1:6379> get w "he" 127.0.0.1:6379> setbit s 1 1 127.0.0.1:6379> setbit s 2 1 127.0.0.1:6379> setbit s 4 1 127.0.0.1:6379> setbit s 9 1 127.0.0.1:6379> setbit s 10 1 127.0.0.1:6379> setbit s 13 1 127.0.0.1:6379> setbit s 15 1 127.0.0.1:6379> getbit w 4 (integer) 1 127.0.0.1:6379> get s "he"
-
bitcount
命令统计指定位置范围内 1 的个数。
eg. 统计签到天数。起始参数[start, end]
为索引值,必须为 8 的倍数。 -
bitpos
命令查找指定范围内出现的第一个 0 或 1。
eg. 查找签到第一天。起始参数[start, end]
为索引值,必须为 8 的倍数。 -
bitfield
可以一次操作多个位,子指令get
/set
/incrby
都可以对指定位片段进行读写,参数u
为无符号,参数i
为有符号。 -
bitfield
处理上限为 64 个连续的位,否则需要执行子指令:127.0.0.1:6379> bitfield w get u4 0 get u3 2 get i4 0 get i3 2 1) (integer) 6 #index=0,无符号取 4 位 2) (integer) 5 #index=2,无符号取 3 位 3) (integer) 6 #index=0,有符号取 4 位 4) (integer) -3 #index=2,有符号取 3 位,注意负数的补码计算
-
Redis 的 integer 是有符号数,最大 64 位,不能传递 64 位无符号值,所以无符号值最大值为 63 位。
-
自增操作需要注意位数据溢出的问题:
- 无符号数自增溢出归零(eg.
u127+1=0
) - 有符号数自增溢出变为最小负数(eg.
i127+1=-128
)
- 无符号数自增溢出归零(eg.
-
bitfield
提供另外两种溢出策略:- 饱和截断 SAT:停留在最大/最小值。
- 失败不执行 FAIL:报错不执行。