Redis深度历险笔记03 Bitmap位图和HyperLogLog

Bitmap 位图

  • 位图不是特殊的数据结构,它其实就是普通的字符串,也就是 byte 数组,用 getbit 和 setbit 来操作,能够统计精确的值。
  • 可以用于布尔型数据的存取,比如用户一年的签到记录,签到了是1,没签到是0,记录365天,通过 bitcount 指令来统计用户一共签到了多少天,每个签到记录只占用一位,365位大约是46个字节大小,用户上亿时,大大节约了内存空间。
使用32位电脑对10亿数据去重排序?

如果用int数组来存储数据的话,需要4G连续的内存空间,而32位电脑最大内存只有4G,没法做到。

可以采用bitmap来解决,实际上就是一个byte数组,数组中的每一个元素是一个字节,一个字节有8位,每一位都可以表示一个数,表示10亿个数只需要128M的内存空间,遍历这10亿数据,把数对应的bit设置为1,遍历完毕后,再对byte进行遍历,就可以从小到大的去重数据了。

32位和64位的含义?

32和64代表计算机内存地址的长度,32位的电脑的内存地址一共有2的32次方个,64位电脑的内存地址有2的64次方个。

为什么32位的电脑的内存地址最大只有4G?

内存的单位是字节,计算机为每个字节分配一个内存地址,对于32位的电脑,内存地址的长度是32位,也就是一共有2的32次方个内存地址,内存的大小也就是2的32次方个字节=2的22次方KB=2的12次方MB=2的2次方GB=4G

HyperLogLog

  • 采用基数算法实现,它设有 16384 个桶进行独立计数,也就是 2 的 14 次方,每个桶占 6 位,2 的 14 次方乘以 6 再除以 8,就等于 12k 字节了。
  • 占用空间小,无论统计多少个数据,最多占用12K的内存。(redis 设有 16384个桶,每个桶里的数据最多需要6位进行存储,16384 x 6 / 8 约等于 12k 字节)
  • 它统计值时存在误差,标准误差为0.81%

HyperLogLog 使用场景

  • 根据用户的IP来统计访问量,需要去重,同一个用户一天之内的多次访问请求只能计数一次,所以每个网页请求都需要带上用户的ID,无论是登录用户还是未登录的游客,都需要一个唯一ID来标识。
  • 最开始容易想到的是为每一个页面设置一个独立的 set 集合来存储当天访问该页面的所有用户ID,但如果页面访问量非常大,比如几千万的 UV,这样 set 集合就会非常大,浪费了空间,而且对于这个 UV 值,一般情况下并不需要多么的精确,比如 100 万和 101 万,对于这个场景,并没什么大的区别。所以想到了采用 redis 的 HyperLogLog 数据结构来实现。
  • HyperLogLog 提供不精确的去重计数方案,标准误差为 0.81%,这个精确度已经可以满足 UV 的统计需求了,而且占用的内存不超过12k。

猜你喜欢

转载自blog.csdn.net/weixin_43338519/article/details/105514449