大数据去重(data deduplication)方案
介绍下经常使用的去重方案:
一、布隆过滤器(BloomFilter)
基本原理:
BloomFilter是由一个长度为m比特的位数组(bit array)与k个哈希函数(hash function)组成的数据结构。位数组均初始化为0,所有哈希函数都可以分别把输入数据尽量均匀地散列。当要插入一个元素时,将其数据分别输入k个哈希函数,产生k个哈希值。以哈希值作为位数组中的下标,将所有k个对应的比特置为1。当要查询(即判断是否存在)一个元素时,同样将其数据输入哈希函数,然后检查对应的k个比特。如果有任意一个比特为0,表明该元素一定不在集合中。如果所有比特均为1,表明该集合有(较大的)可能性在集合中。为什么不是一定在集合中呢?因为一个比特被置为1有可能会受到其他元素的影响,这就是所谓“假阳性”(false positive)。相对地,“假阴性”(false negative)在BloomFilter中是绝不会出现的。
实现参考:
1、Guava中的布隆过滤器:com.google.common.hash.BloomFilter类
2、开源java实现:https://github.com/Baqend/Orestes-Bloomfilter
Redis Bloom Filter扩展:
基于redis做存储后端的BloomFilter实现,可以将bit位存储在redis中,防止计算任务在重启后,当前状态丢失的问题。
二、HyperLogLog(HLL)
HyperLogLog是去重计数的利器,能够以很小的精确度误差作为trade-off大幅减少内存空间占用,在不要求100%准确的计数场景下常用。
在用Flink做实时计算的过程中,可以用HLL去重计数,比如统计UV。
实现参考:
https://github.com/aggregateknowledge/java-hll
结合Flink,下面的聚合函数即可实现从WindowedStream按天、分key统计PV和UV。
WindowedStream<AnalyticsAccessLogRecord, Tuple, TimeWindow> windowedStream = watermarkedStream
.keyBy("siteId")
.window(TumblingEventTimeWindows.of(Time.days(1)))
.trigger(ContinuousEventTimeTrigger.of(Time.seconds(10))); windowedStream.aggregate(new AggregateFunction<AnalyticsAccessLogRecord, Tuple2<Long, HLL>, Tuple2<Long, Long>>() {
private static final long serialVersionUID = 1L; @Override
public Tuple2<Long, HLL> createAccumulator() {
return new Tuple2<>(0L, new HLL(14, 6));
} @Override
public Tuple2<Long, HLL> add(AnalyticsAccessLogRecord record, Tuple2<Long, HLL> acc) {
acc.f0++;
acc.f1.addRaw(record.getUserId());
return acc;
} @Override
public Tuple2<Long, Long> getResult(Tuple2<Long, HLL> acc) {
return new Tuple2<>(acc.f0, acc.f1.cardinality());
} @Override
public Tuple2<Long, HLL> merge(Tuple2<Long, HLL> acc1, Tuple2<Long, HLL> acc2) {
acc1.f0 += acc2.f0;
acc1.f1.union(acc2.f1);
return acc1;
}
});
三、Roaring Bitmap
布隆过滤器和HyperLogLog,虽然它们节省空间并且效率高,但也付出了一定的代价,即:
- 只能插入元素,不能删除元素;
- 不保证100%准确,总是存在误差。
这两个缺点可以说是所有概率性数据结构(probabilistic data structure)做出的trade-off,毕竟鱼与熊掌不可兼得。
如果一定追求100%准确,普通的位图法显然不合适,应该采用压缩位图(Roaring Bitmap)。
将32位无符号整数按照高16位分桶,即最多可能有216=65536个桶,称为container。存储数据时,按照数据的高16位找到container(找不到就会新建一个),再将低16位放入container中。也就是说,一个RBM就是很多container的集合。
实现参考:
https://github.com/RoaringBitmap/RoaringBitmap
使用限制:
- 对去重的字段只能用int或者long类型;
- 对于无法有效压榨的字段(如随机生成的),占用内存较大
四、外部存储去重
利用外部K-V数据库(Redis、HBase之类)存储需要去重的键。由于外部存储对内存和磁盘占用同样敏感,所以也得设定相应的TTL,以及对大的键进行压缩。另外,外部K-V存储毕竟是独立于应用之外的,一旦计算任务出现问题重启,外部存储的状态和内部状态的一致性(是否需要同步)也是要注意的。
外部存储去重,比如Elasticsearch的 _id 就可以做“去重”功能,但是这种去重的只能针对少量低概率的数据,对全量数据去重是不合适的,因为对ES会产生非常大的压力。
参考:
大数据去重(data deduplication)方案的更多相关文章
- PGIS大数据量点位显示方案
PGIS大数据量点位显示方案 问题描述 PGIS在地图上显示点位信息时,随点位数量的增加浏览器响应速度会逐渐变慢,当同时显示上千个点时浏览器会变得非常缓慢,以下是进行的测试: 测试环境: 服务器: C ...
- 大数据 Big Data howto
The Fourth Paradigm: Data-Intensive Scientific Discovery http://research.microsoft.com/en-us/collabo ...
- SQL Server 大数据量分页建议方案
简单的说就是这个 select top(20) * from( select *, rowid = row_number() over(order by xxx) from tb with(noloc ...
- 大数据排序算法:外部排序,bitmap算法;大数据去重算法:hash算法,bitmap算法
外部排序算法相关:主要用到归并排序,堆排序,桶排序,重点是先分成不同的块,然后从每个块中找到最小值写入磁盘,分析过程可以看看http://blog.csdn.net/jeason29/article/ ...
- BitMap算法 .net实现 用于去重并且排序,适用于大型权限管理 ,大数据去重排序
BitMap利用byte特性 针对排序+去重 最佳实践: 100万条数据的排序+去重用时200毫秒左右 static void Main(string[] args) { ]; /*alias*/ ...
- 关于大数据平台ETL可行性方案
今年做过两个公司需求都遇到了实时流入hive的需求,storm入hive有几种可行性方案. 1.storm直接写入hive,storm下面有个stormhive的工具包,可以进行数据写入hive.但是 ...
- 重磅来袭,使用CRL实现大数据分库分表方案
关于分库分表方案详细介绍 http://blog.csdn.net/bluishglc/article/details/7696085 这里就不作详细描述了 分库分表方案基本脱离不了这个结构,受制于实 ...
- c# 大数据量比较时-方案
1.当面临千万条数据量的比较时,从技术的角度来说应该用泛型键值(c#键值由于用了散列算法速度很快).例如前几天我需要查的是 航空公司.出发.到达.返点可以将 航空公司-出发-到达做一个键,返点作为值. ...
- 大数据list去重
MaxList模块主要是对Java集合大数据去重的相关介绍. 背景: 最近在项目中遇到了List集合中的数据要去重,大概一个2500万的数据,开始存储在List中,需要跟一个2万的List去去重. 直 ...
随机推荐
- ps的参数解释
[root@bogon ~]# ps axuUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND user启动进程的用户 pid 表示进程标志 ...
- 【Python】在CentOS6.8中安装pip9.0.1和setuptools33.1
wget https://bootstrap.pypa.io/ez_setup.py python ez_setup.py install --如果这个文件安装需要下载的文件无法下载的话,手动下载,放 ...
- 电子邮箱、邮件地址、网站地址正则表达式!几个有用的RE、regex、regexp!
几个常用的正则表达式! r"\w[-\w\.]*@\w[-\w]*(\.\w[-\w]*)+" 这个是电子邮件地址的. r"<TAG\b[^>]*<(. ...
- kubernets之pod的标签
一 如何查看pod 的日志 1 通过执行命令查看日志信息 kubectl logs pod_name 二 创建带有标签的pod,一个范例的pod创建yaml文件如下所示 2.1 创建带有 ...
- 针对Fluent-Bit采集容器日志的补充
hello,之前我写过<一套标准的ASP.NET Core容器化应用日志收集分析方案>,在公司团队.微信公众号.Github上反映良好. 其中配置Fluent-bit使用Forward协议 ...
- Redis持久化之父子进程与写时复制
之所以将Linux底层的写时复制技术放在Redis篇幅下,是因为Redis进行RDB持久化时,BGSAVE(后面称之为"后台保存")会开辟一个子进程,将数据从内存写进磁盘,这儿我产 ...
- 【C++小知识】#define、enum、const的含义与用法
一.#define 含义 define是宏定义,编译器不对其进行错误检查,在预编译阶段处理,没有作用域限制属于全局常量,在程序中编译器会对定义的常量名以数值进行替换,且每次替换都分配内存,此方法对于大 ...
- 消息中间件——rocketmq环境配置
产生原因 RocketMQ概述 RocketMQ 是一款分布式.队列模型的消息中间件,具有以下特点: 能够保证严格的消息顺序 提供丰富的消息拉取模式 高效的订阅者水平扩展能力 实时的消息订阅机制 亿级 ...
- Excel 多种粘贴方式
一.粘贴为数值. 这个功能是选择性粘贴中最常用的功能.因为excel主要功能之一就是用来做数据分析,把其他格式粘贴为数据格式才能进行数据运算,把带有公式的计算结果粘贴为数值格式可以使复制后的内容不会变 ...
- Web信息收集-目标扫描-Nmap
Web信息收集-目标扫描-Nmap 一.Nmap简介 二.扫描示例 使用主机名扫描: 使用IP地址扫描: 扫描多台主机: 扫描整个子网 使用IP地址的最后一个字节扫描多台服务器 从一个文件中扫描主机列 ...