【Redis】Redis中BitMap(位图)
BitMap介绍
BitMap就是位图,其实也就是字节数组(byte array),用二进制表示,只有 0 和 1 两个数字,位图就是用每一个二进制位来存放或者标记某个元素对应的值。通常是用来判断某个数据存不存在的,因为是用bit为单位来存储所以Bitmap本身会极大的节省储存空间。
如下图字符串在计算机里是由二进制的形式保存的。
我们可以在Redis中设置(SET)一个字符串,可以获取(GET),当然除了获取一个完整的字符串,在Redis中也可以对字符串二进制位进行操作。
Redis Getbit
命令用于对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
返回值
字符串值指定偏移量上的位(bit)。
当偏移量 OFFSET 比字符串值的长度大,或者 key 不存在时,返回 0 。
下面一个案例
127.0.0.1:6379> set key1 big OK 127.0.0.1:6379> getbit key1 0 #获取第一个字母的第一个偏移量 (integer) 0 127.0.0.1:6379> getbit key1 1 #获取第一个字母的第二个偏移量 (integer) 1
BitMap相关操作命令
1. getbit key offset : 对key所存储的字符串值,获取指定偏移量上的位(bit)。
2. setbit key offset value:对key所存储的字符串值,设置或清除指定偏移量上的位(bit):
2) value只能取0或1
3) offset从0开始,即使原位图只能10位,offset可以取1000
案例操作
127.0.0.1:6379> setbit key1 7 1 #将key1第一个字母的最后一个位设置为1 (integer) 0 127.0.0.1:6379> get key1 "cig"
3. bitcount key [start end]:获取位图指定范围中位值为1的个数如果不指定start与end则取所有。
使用bitcount命令查看二进制为1的个数就是13
127.0.0.1:6379> get key1 "cig" 127.0.0.1:6379> bitcount key1 (integer) 13
1) 找不到返回-1。
2) start与end没有设置,则取全部。
3) targetBit只能取0或者1。
BitMap应用场景
1. 用户在线状态。
2. 用户签到。
3. 统计独立用户。
有1亿用户,5千万登陆用户,那么统计每日用户的登录数。每一位标识一个用户ID,当某个用户访问我们的网站就在Bitmap中把标识此用户的位设置为1。
这里做了一个使用set集合和BitMap存储的对比。
数据类型 | 每个 userid 占用空间 | 需要存储的用户量 | 全部占用内存量 |
set(集合) | 32位也就是4个字节(假设userid用的是整型,实际很多网站用的是长整型) | 50,000,000 | 32位 * 50,000,000 = 200 MB |
BitMap | 1 位(bit) | 100,000,000 | 1 位 * 100,000,000 = 12.5 MB |
时间在拉长一点
一天 | 一个月 | 一年 | |
set(集合) | 200M | 6G | 72G |
BitMap | 12.5M | 375M | 4.5G |
计算后发现随着时间的增加,要记录数据量的增加,对比更加明显了,BitMap所占的空间比set(集合)更少。
在看另一个场景假如只有只有100万独立用户,在对比看看。
数据类型 | 每个 userid 占用空间 | 需要存储的用户量 | 全部占用内存量 |
set(集合) | 32位也就是4个字节(假设userid用的是整型,实际很多网站用的是长整型) | 1,000,000 | 32位 * 1,000,000 = 4 MB |
BitMap | 1 位(bit) | 100,000,000 | 1 位 * 100,000,000 = 12.5 MB |
发现BitMap也不是绝对的好,因为Bitmap本身要额外占用了空间。