Redis实战(4)-- BitMap结构与使用
假设一个场景:
当业务需要进行存储不同用户是否进行访问过当前页面时候
可以使用一个hash进行存储,键存储访问时间,值存储对应用户编号;
但是这样会有个问题,大量的hash使用导致所消耗存储空间会很大。
所以这时候可以使用BitMaps进行存储,可以将键设置为访问时间,值设置为对应数组位置上的值,如:
Setbit 2022-9-27 3 1
//具体存储值是(32个位)....000000100 表示3号id用户访问过,这样可以一个二进制位置数组(获取对应的getbit)
BitMaps实现原理
其实现是使用用int字节码的每一位表示一个数字,一个int占32位,可以表示32个数据状态,那么由此可以使用一个Int数组进行标识不同数据的状态:
对应映射关系如图:
tmp[0]可以表示0-31
Tmp[1]可以表示32-63
Tmp[2]可以表示64-95.....以此类推
优点:很大程度节省空间
例如:有5000万用户日活的平台,需要记录当前用户是否登录过
使用集合:id -- long型 (64位) 则存储所需空间为 8*50 000 000 = 400M(每天)
使用bitmaps: 1位存一个用户状态,则需要 1/8 * 50 000 000 = 12.5M
实际使用场景:
当需要进行存储数据状态,而且状态就两种情况下,使用bitmaps进行可以优化存储开销。
常见面试题:
第一题:在限制条件下,可以使用bitmap进行存储,因为一个int类型32位即可以标识32个成员,很大程度上节省空间,所以使用int[]数组进行存储标识哪个自然数出现,且其对应的位置肯定是有序的。
第二题:因为每条URL平均64字节,所以可以转为固定64位长度数值,作为bitmap索引,在哪一位就标识哪个URL,这样只需要计算出对应的URL的64位长度数值即可依据HASH函数算出对应的bitmap中索引位,如果为1标识存在,为0标识不存在。
第三题:可以使用bitmap进行标识,采用用户ID+时间戳进行转化为BitMap的唯一索引,通过hash函数运算,计算出对应的二进制标识位,查看,1为登录过,0为不活跃。
第五题:黑名单标识位为1,白名单标识位为0。
第六题:可以进行黑名单校验,URL黑名单进行拦截这样的,可以使用BitMap实现,经过hash计算后对应标识位值为1则为黑名单拦截,需要进行磁盘精准校验,同时也要考虑哈希冲突的情况处理,0则为正常通过无需校验,可以有效避免无效IO。