redis bitmap

https://www.cnblogs.com/devilwind/p/7374017.html

Redis Bitmaps
    Redis允许使用二进制数据的Key(binary keys) 和二进制数据的Value(binary values)。Bitmap就是二进制数据的value。Redis的 setbit(key, offset, value)操作对指定的key的value的指定偏移(offset)的位置1或0,时间复杂度是O(1)。



一个简单的例子:日活跃用户

    为了统计今日登录的用户数,我们建立了一个bitmap,每一位标识一个用户ID。当某个用户访问我们的网页或执行了某个操作,就在bitmap中把标识此用户的位置为1。在Redis中获取此bitmap的key值是通过用户执行操作的类型和时间戳获得的。

       这个简单的例子中,每次用户登录时会执行一次redis.setbit(daily_active_users, user_id, 1)。将bitmap中对应位置的位置为1,时间复杂度是O(1)。统计bitmap结果显示有今天有9个用户登录。Bitmap的key是daily_active_users,它的值是1011110100100101。

    因为日活跃用户每天都变化,所以需要每天创建一个新的bitmap。我们简单地把日期添加到key后面,实现了这个功能。例如,要统计某一天有多少个用户至少听了一个音乐app中的一首歌曲,可以把这个bitmap的redis key设计为play:yyyy-mm-dd-hh。当用户听了一首歌曲,我们只是简单地在bitmap中把标识这个用户的位置为1,时间复杂度是O(1)。

[java] 

  • Redis.setbit(play:yyyy-mm-dd, user_id, 1)  


Redis.setbit(play:yyyy-mm-dd, user_id, 1)
    今天听过歌曲的用户就是key是play:yyyy-mm-dd的bitmap的位图计数。如果要按周或月统计,只要对这周或这个月的所有bitmap求并集,得出新的bitmap,在对它做位图计数。




    利用这些bitmap做其它复杂的统计也非常容易。例如,统计11月听过歌曲的高级用户(premium user):
(play:2011-11-01∪ play:2011-11-02∪ … ∪ play:2011-11-30)∩premium:2011-11

redis中bit映射被限制在512MB之内,所以最大是0.5*2^30 * 8(每个字节8位)=2^32

缺点就是如果用户稀疏,会浪费内存,对uid hash空间更小

(拼多多面试真题:如何用Redis统计独立用户访问量https://blog.csdn.net/weixin_38405253/article/details/92285696),也使用这种方式

ip白名单算法(pdd活跃用户)

布隆过滤器解决url黑(白)名单

加上本篇文章,3篇文章使用的技术本质都是:

以能够保存到int最大值(hash)2^31-1或unsigned int 最大值2^32-1的bit数组,长度为2^31或2^32,以bit为value的数组

优点是大数据量下省空间,缺点是小数据量下耗空间

比如:

优点:上千万个ip白名单,用hash保存存在大量hash冲突拖累性能

缺点:某个ip白名单10个ip,申请了一个4g长度 512m内存的byte数组

原文地址:https://www.cnblogs.com/silyvin/p/11813847.html