大数据计算:如何仅用1.5KB内存为十亿对象计数

摘要:AddThis的数据分析副总监Matt Abrams在High Scalability上发表了一篇文章,介绍了他们公司如何应对大数据。Matt Abrams表示,AddThis仅仅用了1.5KB内存的内存就计算了十亿个不同的对象,这与他们所使用的计算方法分不开的。

AddThis(前身为Clearspring)的数据分析副总监Matt Abrams在High Scalability上发表了一篇文章,介绍了他们公司如何应对大数据。在这篇文章中,AddThis仅仅用了1.5KB内存的内存就计算了十亿个不同的对象,Matt Abrams主要向我们详解了他们公司在处理过程中使用的方法。

以下为文章全文:

在AddThis,我们喜欢统计数据。对一组中不同元素(也称为“基数”)的数量进行计数,当其数量很大时,这是一个挑战。

为了更好地理解确定的大型成套基数的挑战,让我们想象一下,在你的日志中有一个16个字符的ID,并且你想计算不同ID的数量。这里有一个例子:

4f67bfc603106cb2

16个字符需要用128位来表示。6万5千个ID将需要1MB的空间。我们每天收到30多亿个事件,每个事件都有一个ID。这些ID需要3840亿位或45GB的存储。而这仅仅是ID字段需要的空间!为了得到我们日常活动中的ID基数,我们可以采取一个简单的方法。最简单的想法是使用内存中的哈希集合,其中包含在输入文件中看到的独特的ID列表。即使我们假设3条记录中有1个是唯一的,哈希集合仍需要119GB的RAM,不包括Java需要在内存中存储对象的开销。你需要一台配备几百GB内存的机器来计算不同的元素,并且这只是计算一天的独特ID的成本。如果我们想要数周或数月的数据,这个问题只会变得更加困难。我们身边当然不会有一台配备几百GB内存的空闲机器,所以我们需要一个更好的解决方案。

解决这一问题的常见办法是使用位图。位图可以用来快速、准确地获取一个给定的输入的基数。位图的基本思路是使用哈希函数映射数据集到一个位字段,在位字段里输入的独特元素映射到该字段中的一个位。这产生零碰撞,并减少需要计算每个独特元素到1位的空间。虽然位图大大减少了对空间的要求,但当基数是非常高或你对非常多的不同的组进行计数时,它们仍然有问题。例如,如果我们想要使用位图计数十亿,你将需要十亿位,或需要每个约120 MB的计数器。稀疏的位图可以被压缩,以获得更多的空间效率,但也并不总是有帮助的。

幸运的是,基数估计是一个热门的研究领域。我们已经利用这项研究提供了一个开源实现的基数估计、集员资格检测和top-k算法。

为了了解算法占用的空间与精确度之间的关系,我们用三种不同的计算方法在所有莎士比亚的作品计数了不同单词的数量(90万)。请注意,我们的输入数据集有额外的数据,所以基数高于这个问题答案的标准参考。我们使用的三种技术是:Java HashSet、Linear Probabilistic Counter以及一个Hyper LogLog Counter。这里是结果:

该表显示,我们只使用512字节的空间就可以进行计数,并且误差在3%以内。相比之下,HashMap的计数准确度最高,但需要近10MB的空间,你可以很容易地看到为什么基数估计量是有用的。在实际应用中精度并不是很重要的,这是事实,在大多数网络规模和网络计算的情况下,用概率计数器可能会节省巨大的空间,这是真的。

线性概率计数器

线性概率计数器是高效的空间,并且允许实现者指定所需的精度水平。该算法在注重空间效率时是很有用的,但你需要能够控制你结果里的误差。该算法运行需要两步:第一步,在内存中分配一个初始化为都为0的位图,随后哈希函数被应用于输入数据中的每个条目,哈希函数的结果将映射条目到位图的一个位上,该位设置为1;第二步算法对空位的数量进行计算,并使用这个数字输入到下面的公式来获得估计。

n=-m ln Vn

在方程中,m是位图的大小,n是空位和映射的大小的比率。需要重点注意的是原始位图的大小,可以远小于预期的最大基数。小多少取决于你能忍受多少错误的结果。因为位图的大小、m,小于不同元素的总数,将会有碰撞。这些碰撞都可以节省空间,但同时也造成了错误的估计。所以通过控制原始映射的大小,我们可以估算碰撞的次数,因此我们将在最终结果中看到误差量。

Hyper LogLog

顾名思义,Hyper LogLog计数器的特点是,你仅需要使用loglog(Nmax)+一个常数那么多位就可以对Nmax进行计数。如线性计数器的Hyper LogLog计数器使设计人员能够指定所需的精度公差,在Hyper LogLog的情况下,这是通过定义所需的相对标准偏差和你期望要计数的最大基数。大部分计数通过一个输入数据流、M,并应用一个哈希函数设置h(M)来工作。这将产生一个S = h(M) of {0,1}^∞字符串的可观测结果。通过分割成m子字符串的哈希输入流,并为每个子数据保持m的观测值扩展了Hyper LogLog。使用额外的观测值的平均值,产生一个计数器,其精度提高为m的大小增长,只需要一个在输入集的每个元素上恒定要执行的操作数目。其结果是,这个计数器可以仅使用1.5 kb的空间计算精度为2%的十亿个截然不同的项。与执行 HashSet所需的120 兆字节进行比较,这种算法的效率变得很明显。

合并分布式计数器

我们已经证明了使用上面描述的计数器我们可以估算大集合的基数。但是,如果你的原始输入数据集不适合于单台机器,你能做些什么?这正是我们在AddThis所面临的问题。我们的数据分散在数百台服务器上,并且每个服务器只包含整个数据集子集的一部分。这就是事实,我们可以合并一组分布式计数器的内容,这是至关重要的。这个想法有点令人费解,但如果你花费一些时间去思考这个概念,就会发现其与基本的基数估计值相比并没有太大的不同。因为计数器代表映射中的位作为基数,我们可以采取两个兼容计数器并将其位合并到单一的地图。这个算法已经处理碰撞,所以我们可以得到一个基数估计所需的精密,即使我们从来没有把所有的输入数据到一台机器。这是非常有用的,节省了我们在网络中移动数据的大量时间和精力。

总结

希望这篇文章能帮助你更好地理解这个概念和概率计数器的应用。如果估计大集合的基数是一个问题,而你又碰巧使用一个基于JVM的语言,那么你应该使用stream-lib项目——它提供了其他几个流处理工具以及上文所述的算法的实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/449893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解Nagios配置文件的逻辑关系

1.主配置文件/usr/local/nagios/etc/nagios.cfg a.定义了用户和组 b.定义了某些具体参数 c.定义了配置文件和可以存放配置文件的文件夹 d.通过开头的#号去注释选项以达到关闭配置的效果 e.更改配置后,可以通过命令 /usr/local/nagios/bin/nagios –v /usr/local/na…

云栖社区云栖号(团队博客)攻略【2018版】

云栖社区云栖号是什么? 这是一个为技术团队打造的专区(小站),团队成员的技术文章将在这里汇总,可以帮助团队沉淀优质技术内容、打造技术品牌和影响力等。 云栖号申请条件 点击https://yq.aliyun.com/teams页面右侧的【…

高质高效软件开发组织能力模型

背景至今,我在Motorola网络部工作超过了5年,所在的产品线也是采用统一软件开发过程和敏捷思想(但不是SCRUM)来组织软件开发活动的,但这5年多的工作经历从未引起我象微博上对于SCRUM话题的激烈讨论这样的思考。原因之一可能是,公司…

IntelliJ IDEA编码设置

见:https://www.cnblogs.com/winner-0715/p/6364306.html项目中为了避免乱码等问题应该使用UTF-8编码方式,其实把编码方式设置成UTF-8是创建完项目后就要做的事,按照如图所示进行设置:这里要将Transparent native-to-ascii conversion选项勾选, 否则项目…

C#实现像微信PC版一样的扫码登录功能

现在好些网站都支持扫码登录,感觉上安全了很多,但是本地程序扫码登录的不多,就用C#实现了一下,需要作如下准备 在官网上申请一个企业微信,有条件的话做个企业认证吧,我们的是认证过的,所以账号和本地其他系统的账号是统一的.在应用中创建一个应用,这个是关键,我们扫码就是和它有…

JVM(一)史上最佳入门指南

2019独角兽企业重金招聘Python工程师标准>>> 提到Java虚拟机(JVM),可能大部分人的第一印象是“难”,但当让我们真正走入“JVM世界”的时候,会发现其实问题并不像我们想象中的那么复杂。唯一真正令我们恐惧的…

python量化数据处理小细节(以后还会不断补充)

使用tushare数据源获取数据后处理 以下都是本人在获得数据后,进行量化回测时,处理数据遇到的各种坑以及解决方案,有些甚至都很幼稚,切勿嘲笑 获取数据 导包 import tushare as ts import pandas as pd import matplotlib #(ju…

067:【Django数据库】ORM查询条件详解-range

【Django数据库】ORM查询条件详解-range range:判断某个 field 的值是否在给定的区间中。示例代码如下: # views.py文件内容:from datetime import datetime from django.utils.timezone import make_awaredef index(request):start_time ma…

软件工程师所需掌握的“终极技术”是什么?

最近,我在微博上看到程序员邹欣老师发的一条微博 — “不少大学同学都有一个想法:先做几年技术,然后做管理;也有一些同学说:我技术不行,希望直接找到一个管理的工作,就像PM那样。请看 PM 需要什…

linux中项目部署和日志查看

1 查找进程 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 ps -ef | grep java 查看所有关于java的进程 root 17540 1 0 2009 ? 01:42:27 /usr/java/jdk1.5.0_1…

走技术线,还是技术管理线?

最近因为要给刚毕业的学生做一次演讲,所以就职业发展这类话题先以写博客的形式做一些思考,希望届时能给同学们带来质量更高的内容。我在《驾驭你的“职场布朗运动”》一文中谈了25条职场感悟并提出了“走技术线,还是技术管理线?”…

[Nikon D80]樱花盛开的校园

花开花落,阳春三月,随身背着相机在学校里游走,不断的寻找视角。知道自己拍的不好,总觉得自己拍的片有各式各样的缺陷,也许这就是大师与学徒的区别吧。用好手头的装备,出好片,锻炼Visual Effect …

软件技术发展的驱动力

软件产品的终极目标是为了实现用户需求从而满足人们的需要。也正是为了不断满足人们的需要使得软件行业不断向前发展。比如,新的算法(MPEG-1、MPEG-2、MPEG-4、H.264、……)等的出现都在当时为了满足不同的需要而被发明。然而,人们…

无敌简单快速的文件服务器sgfs

前言 想要构建一个Linux文件服务器?看看下面几个要求是不是你想要的? 1、只需要单节点部署就够了 2、部署启动简单,下载之后,一键启动,一键关闭 3、不需要任何其他的依赖安装,而且运行时占用内存资源少 4、…

CSS margin 属性简介

CSS margin 属性 设置外边距的最简单的方法就是使用 margin 属性。 margin 属性接受任何长度单位,可以是像素、英寸、毫米或 em。 margin 可以设置为 auto。更常见的做法是为外边距设置长度值。下面的声明在 h1 元素的各个边上设置了 1/4 英寸宽的空白:h…

MVC中使用代码创建数据库(code first +mysql+EF)

1.新建一个mvc项目 2.安装mysql需要的几个文件 EntityFramework、MySql.Data(6.9.12)和MySql.Data.Entity (6.9.12) 这里有几点要注意 1.MySql.Data和MySql.Data.Entity 版本必须一致 2.我试用了6.10的版本 要报错 3.我测试没有问…

github 学习使用

博主第一次使用github,所以会将过程全成描述欢迎使用Github注册安装进入仓库,创建、修改、上传文件。强制推送强制覆盖上传文件欢迎使用Github 注册 直接进入github官网:https://github.com 点击sigh up 进行注册 直接填写即可然后验证通过…

软件质量管理之困境与对策思考

相信在不少与软件开发相关的企业内,质量管理部门与软件开发部门在日常运作中形成了如下图所示的“哑铃形”组织结构。 开发部门执行质量管理部门所制定的流程,通过提供证据的形式将各种流程执行后的数据反馈给质量管理部门(包括缺陷率和各种流…

什么是 FreeMarker

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 转自官方文档,只是记录下官方在线手册地址:http://freemarker.foofun.cn/ FreeMarker 是一款 模板引擎&#xff…

C 温故知新 之 指针:数组指针、字符串指针、函数指针

一、数组指针 1.指向数组元素的指针 1、定义:还是那句话通俗的说指针就是地址   数组指针 :数组的起始地址 数组元素指针:数组元素的地址 2、定义一个指向数组元素的指针变量的方法,与之前介绍的指针变量相同。 例如&#…