大数据流处理

我没有去很关注数学,下次补上
突然产生一个疑问,我为什么每次写博客,都没有以尽可能别人看的舒服看的明白为目标,都是以自己想到哪就记录哪?
Bitmap能够将原先需要用32bit存的整数用1bit来表示,它的空间复杂度与要表示的最大的数有关,与有多少个数无关。当要存的数到达64bit的时候占用内存依旧太大
bloom filter是对Bitmap的扩展,有很高效的时间和空间,但是是以牺牲一定的准确度为代价的,以及存在删除困难的问题

Bitmap

应用背景:大数据查找和排序
Bitmap
漫画算法:什么是 Bitmap 算法?
一个byte是8bit,每个bit位代表一个数,如果bit值为1,说明这个数出现过,如果bit值为0.说明没出现过。以byte[0]所示为例,第8,6,3,2位上是1,表示数字7,5,2,1出现过。

在这里插入图片描述
从上图可以看出,逻辑上我们开长度为8的byte数组来存储数据。我们在维护Bitmap时,需要知道每个数对应数组的什么位置,其本质是要知道数字x在A[][8]中的行数和列数(从0开始计数)。但实际时我们用一维数组A[](称之为位数组),他代表一个整数,每个整数有8个bit,可以存储8个数据。
如果数据中的最大值是n,那么需要开的数组大小是(n>>3)+1
数据x的行数index为(x>>3),即落入哪个byte中
数据x的列数position为(x&0x07) 本质上是取后三位来定位列 即落入byte的哪个bit中
A[index]|=1<<position

判断一个数x是否存在:
A[index]&(1<<position)如果为1则存在,说明A[index]的position位bit被置为1,说明x存在。否则bit位为0,x不存在。

清除一个数x:
A[index]&=~(1<<position) 不影响其他位,只把position位清零

当我需要进行排序的时候,遍历一下byte[bit],如果是1就输出下标,那么最后输出的就是排好序的数字。比如上图 1 2 5 7 11

bloom filter

大数据量下的集合过滤—Bloom Filter
讲的很清晰
常见的几个应用场景:

  • cerberus在收集监控数据的时候, 有的系统的监控项量会很大, 需要检查一个监控项的名字是否已经被记录到db过了, 如果没有的话就需要写入db.
  • 爬虫过滤已抓到的url就不再抓,可用bloom filter过滤
  • 垃圾邮件过滤。如果用哈希表,每存储一亿个 email地址,就需要 1.6GB的内存(用哈希表实现的具体办法是将每一个 email地址对应成一个八字节的信息指纹,然后将这些信息指纹存入哈希表,由于哈希表的存储效率一般只有 50%,因此一个 email地址需要占用十六个字节。一亿个地址大约要 1.6GB,即十六亿字节的内存)。因此存贮几十亿个邮件地址可能需要上百 GB的内存。而Bloom Filter只需要哈希表 1/8到 1/4 的大小就能解决同样的问题。

需要补充的是expectedInsertions是字符串总数量
fpp是可接受误差

package com.qunar.sage.wang.common.bloom.filter; 
    
import com.google.common.base.Charsets; 
import com.google.common.hash.BloomFilter; 
import com.google.common.hash.Funnel; 
import com.google.common.hash.Funnels; 
import com.google.common.hash.PrimitiveSink; 
import lombok.AllArgsConstructor; 
import lombok.Builder; 
import lombok.Data; 
import lombok.ToString; 
    
/**
 * BloomFilterTest
 *
 * @author sage.wang
 * @date 18-5-14 下午5:02
 */ 
public class BloomFilterTest { 
        
    public static void main(String[] args) { 
        long expectedInsertions = 10000000; 
        double fpp = 0.00001; 
    
        BloomFilter<CharSequence> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), expectedInsertions, fpp); 
    
        bloomFilter.put("aaa"); 
        bloomFilter.put("bbb"); 
        boolean containsString = bloomFilter.mightContain("aaa"); 
        System.out.println(containsString); 
    
        BloomFilter<Email> emailBloomFilter = BloomFilter 
                .create((Funnel<Email>) (from, into) -> into.putString(from.getDomain(), Charsets.UTF_8), 
                        expectedInsertions, fpp); 
    
        emailBloomFilter.put(new Email("sage.wang", "quanr.com")); 
        boolean containsEmail = emailBloomFilter.mightContain(new Email("sage.wangaaa", "quanr.com")); 
        System.out.println(containsEmail); 
    } 
    
    @Data 
    @Builder 
    @ToString 
    @AllArgsConstructor 
    public static class Email { 
        private String userName; 
        private String domain; 
    } 
    
} 

Sketch

第三次寒假作业 sketch 了解
sketch 是一种基于散列的数据结构,可以在高速网络环境中,实时地存储流量特征信息,只占用较小的空间资源,并且具备在理论上可证明的估计精度与内存的平衡特性。

通过设置散列函数,将具有相同散列值的键值数据存入相同的桶内,以减少空间开销。桶内的数据值作为测量结果,是真实值的近似。利用开辟二维地址空间,多重散列等技术减少散列冲突,提高测量结果的准确度。
一些算法的局部代码和数学推导,代码节选的不是很好,只能将就着看

Count sketch

Sketch调研
C sketch相较于CM多了一组hash函数S1,……St,它们的取值空间均为{+1, -1}

当需要增加某个元素k时,先是和CM一样用原先的一组hash函数找到mapped counters,然后对第i个counter增加Si[k],即有可能加1,也有可能减1。在查询时先得到每个counter的值,再乘上Si[k],并取所有结果的中值为最终估计值。

这里乘Si[k]是因为若高频项的Si[k]值为负,则counter减1的次数多,最终存储的值也为负,因此再乘一次相当于消除符号。而用中值代替平均值是考虑到平均值受极端值的影响较大,相对来说中值更具有鲁棒性

C sketch的思想是通过概率加1和减1,尽量抵消低频项对高频项的干扰,使得对高频项的估计更加精确
讲真这里不是很懂
提出文章《Finding Frequent Items in Data Streams》 Moses Charikar、Kevin Chen、Martin Farach-Colton

Count-Min Sketch(CM算法)

Count-Min Sketch 算法,解决大数据统计难题
我靠,也太直观了叭
CM sketch对元素的频率只会高估而不会低估,且对于重复次数较多的元素的准确率比较高,但是对于出现次数较少的元素的准确率较低
record-all-evict-cold策略

Augmented Sketch

Sketch调研
在这里插入图片描述
在这里插入图片描述
对二元组(k,u)进行插入操作,k为元素,u为次数:

1、如果过滤器中有k,直接对其new_count加u,而old_count不变

2、如果没有且过滤器未满,把k加入并设其new_count = u, old_count =0

3、如果没有且过滤器已满,先把k加入sketch,若此时对k的估计值大于过滤器中的最小值,则将该最小值散列到sketch中共 (new_count - old_count)次,并把k加入过滤器,new_count和old_count都设为原先k的估计值

对于查询操作较为简单:即现在过滤器中查询,有则返回其new_count值,否则到sketch中进行估计

在这种方式中可能会出现需要多次交换(multiple exchanges)的情况,一个例子如下:

在这里插入图片描述
上图中C不在过滤器中且过滤器已满,先将C散列到sketch中,此时对C的估计为9,大于A的8,因此把C加入过滤器,并把A散列6次(8-2)到sketch中。而操作结束后对A的估计值为10,又大于C的9,发生multiple exchanges。

对于这种情况,文章的处理方式是每次最多只进行一次交换(at most one exchange)

A sketch的优点在于节省了很多次的hash计算,因为部分元素聚集在过滤器中。且因为高频项大部分时间都存在过滤器中,而过滤器的计数是完全精确的,因此可以大大提高对高频项的估计情况。

提出文章《Augmented Sketch: Faster and More Accurate Stream Processing》

Augment Sketch的问题在于,filter中的查找是挨个查的,因此比较慢,作者建议存32个hot items。但是在流任务中,需要报告上千个hot items,会导致filter和sketch频繁地互换。

如何查找次数超过k次的元素

数据流基本问题–确定频繁元素(一)
经典的过半元素查找问题

Lossy Counting Algorithm

实时大数据流上的频率统计:Lossy Counting Algorithm

简言之将数据流切分为多个窗口,在每个窗口中对item频次进行统计,然后整体-1,把频次为0的evict掉。最后汇总多个窗口

Sticky sampling 算法

数据流基本问题–确定频繁元素(二)lossy counting和sticky sampling
我没有看懂,之后找论文看,先不记录

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据流处理框架介绍 ⼤数据流处理框架介绍   实时流处理简单概述:实时是说整个流处理相应时间较短,流式计算是说数据是源源不断的,没有尽头的。实时流处理⼀般是将业务系 统产⽣的数据进⾏实时收集,交由流处理框架进⾏数据清洗,统计,⼊库,并可以通过可视化的⽅式对统计结果进⾏实时的展⽰。本⽂涉及 到的框架或技术有 Flume,Logstash,kafka,Storm, SparkStreaming等。   实时流处理的的流程与技术选型 :   ⼀、⽇志收集   由于业务系统⼀般是游离与流处理集群如SparkStreaming、Storm之外的,所以我们需要对业务系统的数据进⾏实时收集。这就⽤到了 ⽇志收集框架,⽇志收集框架主要需要解决三个问题:数据从哪⼉来,数据到哪⼉去,实时收集。因为在流处理中为了防⽌突发或激增流量 压垮流处理集群,通常将收集过后的数据输出到kafka分布式消息系统,然后流处理集群去消费kafka中的数据,下⾯介绍两种常⽤的⽇志收 集框架以及他们如何对接kafka.   1).Apache Flume   这是⼀个apache的顶级项⽬,所以域名为flume.apache, 下⾯是官⽹上的原理图,Flume框架把每个收集任务都定义为⼀个Agent(这是 ⼀个JAVA进程),他有三个基本组件Source、Channel、Sink。   source:收集数据,可以对接各种常⽤数据源,如⽂件(exec source),kafka(kafka source),jms(java消息系统)等。   channel:source组件把数据收集来以后,临时存放在channel(管道)中,即channel组件在agent中是专门⽤来存放临时数据的,并起 到数据缓冲的作⽤。常⽤的channel有memory chanel 、jdbc chanel 、file channel 等等。   sink:sink组件是⽤于从channel中取数据并送到⽬的地的组件,⽬的地包括hdfs、logger、avro、thrift、file、hbase等。   其实flume的使⽤就是编写配置⽂件,下⾯是使⽤flume将Nginx的⽇志对接kafka的配置⽂件,我们将该收集任务命名为   exec-memory-kafka,只需如下编写:   #配置source、sink、channel   exec-memory-kafka.sources=exec-source #指定source (数据从哪⼉来),可以指定多个数据源,⽤逗号分隔。   exec-memory-kafka.sinks=kafka-sink #指定sink(数据到哪⼉去)   exec-memory-kafka.channels=memory-channel #指定channel   #source详细配置   exec-memory-kafka.sources.exec-source.type=exec 执⾏操作系统命令   exec-memory-kafka.sources.exec-sourcemand=sudo tail -F /var/log/nginx/access.log #监控Nginx⽇志⽂件   exec-memory-kafka.sources.exec-source.shell=/bin/sh -c #shell命令的前缀   #channel 详细配置   exec-memory-kafka.channels.memory-channel.type=memory #内存channel   #sink详细配置   exec-memory-kafka.sinks.kafka-sink.type=org.apache.flume.sink.kafka.KafkaSink #类型 为kafka sink   exec-memory-kafka.sinks.kafka-sink.brokerList=hadoop000:9092 #kafaka服务的地址,多个⽤逗号分隔   exec-memory-kafka.sinks.kafka-sink.topic=test1 #指定主题   exec-memory-kafka.sinks.kafka-sink.batchSize=5 #指定每多少条收集⼀次,这⾥是每5条发送⼀次。   exec-memory-kafka.sinks.kafka-sink.requiredAcks=1 #使kafka对是否收到数据进⾏确认,确保数据不会丢失   #为sink和source指定channel   exec-memory-kafka.sources.exec-source.channels=memory-channel   exec

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值