Redis中Bitmap的使用示例
在日常开发过程中,经常会有一些 bool 类型数据需要存取。比如记录用户一年内签到的次数,签了是 1,没签是 0。如果使用 key-value 来存储,那么每个用户都要记录 365 次,当用户成百上亿时,需要的存储空间将非常巨大。解决这个问题,可以使用redis中的位图。
位图(bitmap)同样属于 string 数据类型。Redis 中一个字符串类型的值最多能存储 512 MB 的内容,每个字符串由多个字节组成,每个字节又由 8 个 Bit 位组成。位图结构正是使用“位”来实现存储的,它通过将比特位设置为 0 或 1来达到数据存取的目的,这大大增加了 value 存储数量,它存储上限为2^32。
位图本质上就是一个普通的字节串,也就是 bytes 数组。您可以使用getbit/setbit命令来处理这个位数组,位图的结构如下所示:
位图适用于一些特定的应用场景,比如用户签到次数、或者登录次数等。上图是表示一位用户 10 天内来网站的签到次数,1 代表签到,0 代表未签到,这样可以很轻松地统计出用户的活跃程度。相比于直接使用字符串而言,位图中的每一条记录仅占用一个 bit 位,从而大大降低了内存空间使用率。
Redis 官方也做了一个实验,他们模拟了一个拥有 1 亿 2 千 8 百万用户的系统,然后使用 Redis 的位图来统计“日均用户数量”,最终所用时间的约为 50ms,且仅仅占用 16 MB内存。
位图应用原理
某网站要统计一个用户一年的签到记录,若用 sring 类型存储,则需要 365 个键值对。若使用位图存储,用户签到就存 1,否则存 0。最后会生成 00010101… 这样的存储结果,其中每天的记录只占一位,一年就是 365 位,约为 46 个字节。如果只想统计用户签到的天数,那么统计 1 的个数即可。
位图操作的优势,相比于字符串而言,它不仅效率高,而且还非常的节省空间。
Redis 的位数组是自动扩展的,如果设置了某个偏移位置超出了现有的内容范围,位数组就会自动扩充。
位图常用命令
1) SETBIT命令
用来设置或者清除某一位上的值,其返回值是原来位上存储的值。key 在初始状态下所有的位都为 0 ,示例如下:
其中 offset 表示偏移量,从 0 开始。示例如下:
OK
#设置偏移量offset为0
127.0.0.1:6379> SETBIT user:1 0 1
(integer) 0
#当对应位的字符是不可打印字符,redis会以16进制形式显示
127.0.0.1:6379> GET user:1
“\xe1”
2) GETBIT命令
用来获取某一位上的值。示例如下:
(integer) 1
当偏移量 offset 比字符串的长度大,或者当 key 不存在时,返回 0。
(integer) 0
redis> GETBIT bits 100000
(integer) 0
3) BITCOUNT命令
统计指定位区间上,值为 1 的个数。语法格式如下:
示例如下:
(integer) 8
通过指定的 start 和 end 参数,可以让计数只在特定的字节上进行。start 和 end 参数和 GETRANGE 命令的参数类似,都可以使用负数,比如 -1 表示倒数第一个位, -2 表示倒数第二个位。.
4)Redis Bitop 命令
对一个或多个保存二进制位的字符串 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 。
除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入。
场景
统计当日活跃用户
每日活跃统计创建一个bitmap键,当用户活跃了根据用户id的偏移量来设置
对应的位为1
用户签到
每个用户创建一个位图的键,以某一天为基础,之后的天数距离这一天的天数为偏移量,
如果用户点击了签到,则设置对用的偏移位为1。
到此这篇关于Redis中Bitmap的使用示例的文章就介绍到这了,更多相关Redis Bitmap内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!