最近碰到手机设备匹配的业务, 用户在我司后台可以上传人群包, 里面存放的是设备的MD5标识符; 一个人群包大概有千万级的MD5数据, 与广告请求所携带设备标识进行匹配.
尝试插入1kw条数据, key为设备MD5值, value为1, 此时Redis中存在1kw条key-value键值对.
通过 info 指令查看内存占用:
8bit = 1b = 0.001kb
bitmap即位图, 就是通过最小的单位bit来进行0或者1的设置,表示某个元素对应的值或者状态。
一个bit的值,或者是0,或者是1;也就是说一个bit能存储的最多信息是2。
场景: 有用户id分别为1, 2, 3, 4, 5, 6, 7, 8的用户, 其中用户2, 5在今日登录, 统计今
日登录用户
采用位图存储: 用户id为偏移量, 可以看做是在位图中的索引, value为true
通过 bitcount 获取登录用户数为2:
测试offset从1-1kw连续整数时候的内存占用:
可以发现内存占用仅为 1.19MB, 1个亿的数据也才12MB, 极大的减少了内存;
由于我们的业务没有如此完美的情况出现, 采用设备MD5的hash做Offset, 不会出现连续正整数的情况;
各常用Hash函数性能对比: https://byvoid.com/zhs/blog/string-hash-compare/
所以我们接下来测试1kw条MD5数据的位图内存占用:
查看Redis内存占用:
问题: 为什么同样1kw的bitmap, MD5数据的Hash占用会比 测试一 的多200倍?
将32位无符号整数按照高16位分桶,即最多可能有216=65536个桶,称为container。存储数据时,按照数据的高16位找到container(找不到就会新建一个),再将低16位放入container中。也就是说,一个RBM就是很多container的集合。
图中示出了三个container:
1kw条MD5数据的插入: