Redis HyperLogLog
Redis 在 2.8.9 版本添加了 HyperLogLog 结构。Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
HyperLogLog
Hyper LogLog计数器就是估算Nmax为基数的数据集仅需使用loglog(Nmax)+O(1) bits就可以。如线性计数器的Hyper LogLog计数器允许设计人员指定所需的精度值,在Hyper LogLog的情况下,这是通过定义所需的相对标准差和预期要计数的最大基数。大部分计数器通过一个输入数据流M,并应用一个哈希函数设置h(M)来工作。这将产生一个S = h(M) of {0,1}^∞字符串的可观测结果。通过分割哈希输入流成m个子字符串,并对每个子输入流保持m的值可观测 ,这就是相当一个新Hyper LogLog(一个子m就是一个新的Hyper LogLog)。利用额外的观测值的平均值,产生一个计数器,其精度随着m的增长而提高,这只需要对输入集合中的每个元素执行几步操作就可以完成。其结果是,这个计数器可以仅使用1.5 kb的空间计算精度为2%的十亿个不同的数据元素。与执行 HashSet所需的120 兆字节进行比较,这种算法的效率很明显。
误差率
合并测试case
import java.io.IOException; import java.text.DecimalFormat; import java.text.NumberFormat; import com.clearspring.analytics.stream.cardinality.CardinalityMergeException; import com.clearspring.analytics.stream.cardinality.HyperLogLog; public class HyperLogLogMerge { private static NumberFormat nf = new DecimalFormat("####.#####%"); public static void main(String[] args) throws IOException, CardinalityMergeException { int record = 5000000; HyperLogLog aHyperLogLog = exec(18,record,"xx"); HyperLogLog bHyperLogLog = exec(18,record,"yy"); HyperLogLog cHyperLogLog = exec(18,1200,"yy"); //执行合并 HyperLogLog tHyperLogLog1 = (HyperLogLog)aHyperLogLog.merge(bHyperLogLog); //重复数据合并 HyperLogLog tHyperLogLog2 = (HyperLogLog)tHyperLogLog1.merge(cHyperLogLog); System.out.printf("merge total1 = %d \n",tHyperLogLog1.cardinality()); System.out.printf("merge total2 = %d \n",tHyperLogLog2.cardinality()); } public static HyperLogLog exec(int log2m , int record,String keySuffix )throws IOException { HyperLogLog hyperLogLog1 = new HyperLogLog(log2m); for(int i=0;i<record;i++) { hyperLogLog1.offer(i+"haperloglog"+keySuffix); } double errorRate = (double)(record-hyperLogLog1.cardinality())/(double)record; System.out.printf("log2m=%d ,object.size=%f kb ,cardinality/record=%d/%d ,errorRate=%s \n", log2m,((double)hyperLogLog1.getBytes().length)/1024d, hyperLogLog1.cardinality(),record,nf.format(errorRate)); return hyperLogLog1; } } log2m=18 ,object.size=170.675781 kb ,cardinality/record=4987682/5000000 ,errorRate=0.24636% log2m=18 ,object.size=170.675781 kb ,cardinality/record=4989420/5000000 ,errorRate=0.2116% log2m=18 ,object.size=170.675781 kb ,cardinality/record=1201/1200 ,errorRate=-0.083333% merge total1 = 10004502 merge total2 = 10004502
内存使用测试Case
import java.io.IOException; import java.text.DecimalFormat; import java.text.NumberFormat; import com.clearspring.analytics.stream.cardinality.HyperLogLog; public class HyperLogLogzMemory { private static NumberFormat nf = new DecimalFormat("####.#####%"); public static void main(String[] args) throws IOException { int record = 5000000; exec(12,record); exec(15,record); exec(18,record); exec(21,record); exec(25,record); } public static void exec(int log2m , int record )throws IOException { HyperLogLog hyperLogLog1 = new HyperLogLog(log2m); for(int i=0;i<record;i++) { hyperLogLog1.offer(i+"haperloglog"); } double errorRate = (double)(record-hyperLogLog1.cardinality())/(double)record; System.out.printf("log2m=%d ,object.size=%f kb ,cardinality/record=%d/%d ,errorRate=%s \n", log2m,((double)hyperLogLog1.getBytes().length)/1024d, hyperLogLog1.cardinality(),record,nf.format(errorRate)); } } log2m=12 ,object.size=2.675781 kb ,cardinality/record=4901798/5000000 ,errorRate=1.96404% log2m=15 ,object.size=21.343750 kb ,cardinality/record=4971119/5000000 ,errorRate=0.57762% log2m=18 ,object.size=170.675781 kb ,cardinality/record=4991409/5000000 ,errorRate=0.17182% log2m=21 ,object.size=1365.343750 kb ,cardinality/record=4992590/5000000 ,errorRate=0.1482% log2m=25 ,object.size=21845.343750 kb ,cardinality/record=5000356/5000000 ,errorRate=-0.00712%
引用HyperLogLog包
<dependency> <groupId>com.clearspring.analytics</groupId> <artifactId>stream</artifactId> <version>2.7.0</version> </dependency>
资料
http://www.redis.net.cn/tutorial/3513.html
https://github.com/addthis/stream-lib
http://blog.csdn.net/hguisu/article/details/8433731
http://highscalability.com/blog/2012/4/5/big-data-counting-how-to-count-a-billion-distinct-objects-us.html
https://blog.csdn.net/u012160954/article/details/52768734
相关推荐
- **HyperLogLog介绍**:一种用于估计不重复元素数量的数据结构。 - **独特用户计数**:通过HyperLogLog高效地统计网站的独特访客数。 ### 总结 以上内容涵盖了从基础到高级的Redis知识点,不仅包括安装配置、...
在介绍HyperLogLog时,我们通常会讨论以下几个核心知识点: 1. **基本原理**:HyperLogLog算法通过使用hash函数将输入元素映射到一系列的桶(bucket)中,并记录每个桶中元素的最大前导零(leading zeros)数量。...
Redis 种除了常见的字符串 String、字典 Hash、列表 List、集合 Set、有序集合 SortedSet 等等之外,还有一些不常用的数据类型,这里着重介绍三个。下面话不多说了,来一起看看详细的介绍吧。 BitMap BitMap 就是...
介绍 如果您喜欢来创建您的在线演示文稿,就像为您提供的站点管理工具,并且喜欢因其简单干净的外观,这里有一种使用 Jekyll、Markdown 和 Reveal.js 创建演示文稿的简单方法。 请参阅使用此存储库中的内容和...
HyperLogLog是一种用于统计唯一值的特殊数据结构,操作部分介绍了如何将元素添加至HyperLogLog、获取HyperLogLog的基数估算值和合并多个HyperLogLog。 ### 发布订阅 发布订阅是Redis提供的消息通信模式,手册中的这...
### Redis的概要介绍与分析 #### 一、Redis简介 Redis(Remote Dictionary Server)是一种开源的、高性能的键值存储系统。它以其快速的数据访问速度和灵活的数据结构,在缓存、消息队列、实时数据分析、会话存储等...
本文将详细介绍一种基于微服务架构的网络爬虫服务化方案,旨在优化数据采集、存储和监控流程。 首先,我们来看网络爬虫的分层架构。这一架构主要分为四个层面:硬件设备层、组件和服务层、爬虫应用解析和网关层以及...
### Redis的介绍与深入使用详解 #### 一、Redis简介 Redis是一个开源的内存数据库,作为NoSQL数据库的一种,以其高性能、丰富的数据结构支持、持久化能力、复制、集群及发布/订阅等特性而广受好评。由于这些特性,...
6. 文档:项目介绍、使用指南、API文档等,帮助用户理解和使用HyperBitBit。 要深入学习和利用这个项目,你可以按照以下步骤进行: 1. 解压文件并查看README:通常,README文件会提供项目的基本信息、安装指南和...
《360 Redis 生态圈介绍》 360 Redis 生态圈是360公司构建的一套基于Redis开源数据库的全面解决方案,旨在提供高效、稳定、可扩展的数据存储服务。Redis,全称Remote Dictionary Server,是一种内存数据结构存储...
│ 10.Redis 中的 HyperLogLog.mp4 │ 11.布隆过滤器[问题场景].mp4 │ 12.布隆过滤器[概念介绍].mp4 │ 13.布隆过滤器[原理介绍].mp4 │ 14.布隆过滤器[安装与启动].mp4 │ 15.布隆过滤器[基本用法].mp4 │ ...
│ 10.Redis 中的 HyperLogLog.mp4 │ 11.布隆过滤器[问题场景].mp4 │ 12.布隆过滤器[概念介绍].mp4 │ 13.布隆过滤器[原理介绍].mp4 │ 14.布隆过滤器[安装与启动].mp4 │ 15.布隆过滤器[基本用法].mp4 │ ...
│ 10.Redis 中的 HyperLogLog.mp4 │ 11.布隆过滤器[问题场景].mp4 │ 12.布隆过滤器[概念介绍].mp4 │ 13.布隆过滤器[原理介绍].mp4 │ 14.布隆过滤器[安装与启动].mp4 │ 15.布隆过滤器[基本用法].mp4 │ ...
│ 10.Redis 中的 HyperLogLog.mp4 │ 11.布隆过滤器[问题场景].mp4 │ 12.布隆过滤器[概念介绍].mp4 │ 13.布隆过滤器[原理介绍].mp4 │ 14.布隆过滤器[安装与启动].mp4 │ 15.布隆过滤器[基本用法].mp4 │ ...
以下是对Redis中提及的一些核心概念的详细介绍: 1. **基本数据类型**: - **字符串(String)**: 最基础的数据类型,可以存储任何字符串或二进制数据,如数字、JSON对象等。 - **哈希(Hash)**: 用于存储键值对...
使用 Redis 的 set 实现点赞,zset 实现关注,HyperLogLog 统计 UV,Bitmap 统计 DAU;使用 Kafka 处理发送评论、点赞和关注等系统通知,起到解耦和异步调用的作用;使用 Elasticsearch 对帖子搜索功能进行重构,...
以下是对这些数据类型的简单介绍及其常用命令和应用场景。 **String** String 是 Redis 最基础的数据类型,可以存储字符串、数字等类型的数据。它的值最多可以存储 512MB。常用命令包括 `set`、`get`、`mset`、`...
7. 模块系统:Redis提供了丰富的模块系统,如Geo(地理位置)、HyperLogLog(稀疏集合计数)等,可扩展其功能。 二、Redis的主要应用场景 1. 缓存:Redis常用于减轻数据库压力,缓存热点数据,提高应用性能。 2. ...