企业级Redis开发运维从入门到实践 (13)— HyperLogLog

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zx711166/article/details/82855536

HyperLogLog是做什么的

  1. 基于HyperLogLog算法:极小空间完成独立数量统计,Redis中实现的HyperLogLog,只需要12K内存,在标准误差0.81%的前提下,能够统计 2 64 2^{64} 个数据。
  2. 本质还是字符串。
redis> type hyperloglog_key
string

redis中hyperloglog实现

Redis正是基于HyperLogLog Counting(HLL)算法实现的HyperLogLog结构,用于统计一组数据集合中不重复的数据个数。

Redis中统计数组大小设置为,hash函数生成64位bit数组,其中用来找到统计数组的位置,剩下50位用来记录第一个1出现的位置,最大位置为50,需要记录。

那么统计数组需要的最大内存大小为: 基数估计的标准误差位。

HyperLogLog的相关命令

pfadd
  • pfadd key element [element …]:向hyperloglog添加元素。
  • 时间复杂度:每添加一个元素的复杂度为 O(1) 。
  • 如果给定键已经是一个 HyperLogLog , 那么这种调用不会产生任何效果。
  • 但如果给定的键不存在, 那么命令会创建一个空的 HyperLogLog , 并向客户端返回 1 。
# 返回值:整数回复,如果 HyperLogLog 的内部储存被修改了, 那么返回 1 , 否则返回 0 。
redis> pfadd 2017_03_06:unique:ids "uuid-1" "uuid-2" "uuid-3" "uuid-4"
(integer) 1
pfcount
  • pfcount key [key …]:计算hyperloglog的独立总数。
  • 时间复杂度:当命令作用于单个 HyperLogLog 时, 复杂度为 O(1) , 并且具有非常低的平均常数时间。 当命令作用于 N 个 HyperLogLog 时, 复杂度为 O(N) , 常数时间也比处理单个 HyperLogLog 时要大得多。
redis> pfcount 2017_03_06:unique:ids
(integer) 4

redis> pfadd 2017_03_06:unique:ids "uuid-1" "uuid-2" "uuid-3" "uuid-90"
(integer) 1

redis> pfcount 2017_03_06:unique:ids
(integer) 5
pfmerge
  • pfmerge destkey sourcekey [sourcekey …]:合并多个hyperloglog。
  • 时间复杂度:O(N) , 其中 N 为被合并的 HyperLogLog 数量, 不过这个命令的常数复杂度比较高。
# 添加 key 是 2016_03_06:unique:ids
redis> pfadd 2016_03_06:unique:ids "uuid-1" "uuid-2" "uuid-3" "uuid-4"
(integer) 1
redis> pfcount 2016_03_06:unique:ids
(integer) 5

#添加 key 是 2016_03_05:unique:ids
redis> pfadd 2016_03_05:unique:ids "uuid-4" "uuid-5" "uuid-6" "uuid-7"
(integer) 1
redis> pfcount 2016_03_05:unique:ids
(integer) 4

# 合并 2016_03_06:unique:ids、2016_03_05:unique:ids
redis> pfmerge 2016_03_05_06:unique:ids 2016_03_05:unique:ids 2016_03_06:unique:ids
OK
reids> pfcount 2016_03_05_06:unique:ids
(integer) 7

内存消耗(百万独立用户)

elements = ""
key = "2016_05_01:unique:ids"
for i in 'seq 1 1000000'
do
	elements = "${elements} uuid-"${i}
	if [[ $((i%1000)) == 0 ]]
	then
		redis-cli pfadd ${key} ${elements}
		elements = ""
	fi
done
内存消耗
一天 15 K B 15KB
一个月 15 K B 30 = 450 K B 15KB*30 = 450KB
一年 15 K B 365 5 M B 15KB*365 \approx 5MB

使用经验

  1. 是否能容忍错误率?(错误率:0.81%)
redis> pfcount 2016_05_01:unique:ids(integer)
1009838
  1. 是否需要单条数据?(无法获取单条数据)

猜你喜欢

转载自blog.csdn.net/zx711166/article/details/82855536