首先,HyperLogLog与布隆过滤器都是针对大数据统计存储应用场景下的知名算法。html
HyperLogLog是在大数据的状况下关于数据基数的空间复杂度优化实现,布隆过滤器是在大数据状况下关于检索一个元素是否在一个集合中的空间复杂度优化后的实现。git
在传统的数据量比较低的应用服务中,咱们要实现数据基数和数据是否存在分析的功能,一般是简单的把全部数据存储下来,直接count一下就是基数了,而直接检索一个元素是否在一个集合中也很简单。github
但随着数据量的急剧增大,传统的方式已经很难达到工程上的需求。过大的数据量不管是在存储仍是在查询方面都存在巨大的挑战,不管咱们是用位存储仍是树结构存储等方式来优化,都无法达到大数据时代的要求或者是性价比过低。redis
因而HyperLogLog与布隆过滤器这两个算法就很好的派上了用场。他们的使用能够极大的节约存储空间,做为代价,则是牺牲了一个小几率的准确性,这能够很好的达到工程上的需求,对于那些要求准确度没那么高,但数据量巨大的需求是很是合适的。算法
HyperLogLog原理数组
最直白的解释是,给定一个集合 S,对集合中的每个元素,咱们作一个哈希,假设生成一个 16 位的比特串,从全部生成的比特串中挑选出前面连续 0 次数最多的比特串,假设为 0000000011010110,连续 0 的次数为 8,所以咱们能够估计该集合 S 的基数为 2^9。固然单独用这样的单一估计偶然性较大,致使偏差较大,所以在实际的 HyperLogLog 算法中,采起分桶平均原理了来消除偏差。(这段话引用了 HyperLogLog 原理 中的描述,还有一些细节实现 感兴趣可阅读 https://blockchain.iethpay.com/hyperloglog-theory.html)函数
特色:实现牺牲了必定的准确度(在一些场景下是能够忽略的),但却实现了空间复杂度上的极大的压缩,能够说是性价比很高的。大数据
虽然基数不彻底准确,可是能够符合,随着数量的递增,基数也是递增的。优化
布隆过滤器原理插件
布隆过滤器(Bloom Filter)的核心实现是一个超大的位数组和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k,以上图为例,具体的操做流程:假设集合里面有3个元素{x, y, z},哈希函数的个数为3。首先将位数组进行初始化,将里面每一个位都设置为0。对于集合里面的每个元素,将元素依次经过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数组上面的一个点,而后将位数组对应的位置标记为1。查询W元素是否存在集合中的时候,一样的方法将W经过哈希映射到位数组上的3个点。若是3个点的其中有一个点不为1,则能够判断该元素必定不存在集合中。反之,若是3个点都为1,则该元素可能存在集合中。注意:此处不能判断该元素是否必定存在集合中,可能存在必定的误判率。能够从图中能够看到:假设某个元素经过映射对应下标为4,5,6这3个点。虽然这3个点都为1,可是很明显这3个点是不一样元素通过哈希获得的位置,所以这种状况说明元素虽然不在集合中,也可能对应的都是1,这是误判率存在的缘由。(这段话与图片引用于 布隆过滤器(Bloom Filter)的原理和实现 中的描述,还有一些细节实现 感兴趣可阅读 http://www.javashuo.com/article/p-aenfkllo-mo.html)
特色:巧妙的使用hash算法和bitmap位存储的方式,极大的节约了空间。
因为主要用的是hash算法的特色,全部知足和hash算法相同的规则:当过滤器返回 true时(表示颇有可能该值是存在的),有必定几率是误判的,便可能不存在;当过滤器返回false时(表示肯定不存在),是能够彻底相信的。
咱们换个数据的角度来看规则:当数据添加到布隆过滤器中时,对该数据的查询必定会返回true;当数据没有插入过滤器时,对该数据的查询大部分状况返回false,但有小几率返回true,也就是误判。
咱们知道它最终知足的规则和hash的规则是一致的,只是组合了多个hash,使用了bitmap来存储,大大优化了存储的空间和判断的效率。
redis中的HyperLogLog
在redis中对HyperLogLog 的支持早在2.8.9的时候就有了。它的操做很是简单
redis中的布隆过滤器
在redis中的布隆过滤器的支持是在redis4.0后支持插件的状况下,经过插件的方式实现的 ,redis的布隆过滤器插件地址:https://github.com/RedisLabsModules/rebloom
它的操做也很简单,如下为几个主要命令,其它命令请参考文档 https://github.com/RedisLabsModules/rebloom/blob/master/docs/Bloom_Commands.md
BF.RESERVE {key} {error_rate} {size} 建立一个布隆过滤器 key为redis存储键值,error_rate 为错误率(大于0,小于1),size为预计存储的数量(size是比较关键的,须要根据本身的需求状况合理估计,设置过小的话会增大错误率,设置太大会占用过多没必要要的空间)
BF.ADD {key} {item} 添加值到布隆过滤器中(当过滤器不存在的时候会,会以默认值自动建立一个,建议最好提早建立好) key为redis存储键值,item为值(如须要添加多个,请使用BF.MADD 可同时添加多个)
BF.EXISTS {key} {item} 判断值是否存在过滤器中 true(表示极可能存在) false (表示绝对不存在)
参考文章:
https://blockchain.iethpay.com/hyperloglog-theory.html hyperloglog原理
http://www.javashuo.com/article/p-aenfkllo-mo.html 布隆过滤器原理
http://redisdoc.com/hyperloglog/index.html redis的hyperloglog的使用
https://github.com/RedisLabsModules/rebloom/blob/master/docs/Bloom_Commands.md redis的布隆过滤器的使用