DSP

广告效果数据的实时计算与分析(Druid)(一)

2019-07-13 17:35发布

我是做SSP-供应方平台服务的,工作中除了负责SSP 管理后台的需求开发(如,媒体应用和位置的管理、流量分配、效果数据的报表展示、SDK性能分析等)之外,最主要的是负责SSP广告效果数据的实时统计与分析,为媒体主及运营人员提供可靠的数据,方便其分析或查找问题及时调整策略提高SSP的收入及为媒体提供高质量的广告。 广告平台的基本概念介绍 广告收入占据这互联网公司的大半收入,很多免费软件、视屏播放器、音频播放器、杀毒软件或者其他的APP等都是靠广告来赚钱的,广告的形式有多种,如开屏、插屏、横幅、信息流、视屏广告等,广告平台根据面向的用户或者是提供的功能不同又分为:DSP、ADX、SSP、DMP这个四个平台,下面是这四个平台的基本概念:
DSP-需求方平台,也就是广告主服务平台,广告主可以通过DSP平台设置自己想要的受众目标以及愿意出多少钱购买这些受众的曝光等操作完成广告投放,面向广告购买方。
SSP-供应方平台,它是媒体服务平台,媒体方可以通过SSP平台完成广告资源的管理,如流量分配、价格、筛选等等,面向广告售卖方。
ADX-广告交易平台,连接买方和卖方,ADX将媒体的广告流量以拍卖的方式卖给DSP。
DMP-数据管理平台,整合各方数据并提供数据分析,数据管理、数据调用等,用来指导广告主进行广告优化和投放决策。 SSP广告效果数据现有架构 广告效果数据量是巨大的,从一天的一两千万的数据慢慢的增长到数十亿,一天要处理几十GB的数据,数据延时的在10分钟,即当前时间能要能看到10分钟之前的所有效果数据,这个对服务的可用和实时还是挺有压力和挑战的,目前有很多实时计算框架,如spark/storm 都具有这个能力,我们采用的是Spark Streaming+Metaq+Flume+Hadoop+Hive的架构实现广告效果数据的准实时统计与分析。整个流程如下:
SDK向SSP服务端发情广告请求,SSP在接收到SDK的请求后根据协议解析相关的请求参数,根据媒体的位置上配置的流量进行分配向不同的ADX发送请求等待广告的放回,在等到超时或者ADX返回了广告后,拼装广告素材返回给SDK,并把该次请求广告的位置及ADX返回的广告填充等信息通过发送至Flume,然后Flume 集中广告数据发送没Metaq 集群,Spark Streaming 不停的消费Metaq中的消息,并把原始数据存储到Hive表中(方便后面做其他离线数据分析),然后读取Hive中的数据根据规则进行分析与计算并把结果写到MySql中进行报表展示。 该架构目前处理几十GB的数据,还没有看到瓶颈与压力(一般会调整CPU数量及内存的大小来面对越来越多的数据),但是随着结果数据的越来越多MySql中的数据量越来越大,达到几千万数据的时候查询所需的时间,单单优化SQL优化索引是很难解决问题,此时就需要分库分表,如根据应用或者时间等进行分表,但分库分表的缺点也是很明显的就是本来一条SQL能完成的事,分库分表后需要更复杂的方案来实现同样的功能、例如根据时间分组,一个月一张表,此时需要根据应用维度来分析数据(当然你也可以按应用分表来解决问题,这里只是举个例子)查询应用的近两个月的总的请求量,此时如果不分表:select sum(requestTime) ,appId from stat_table group by appId where stat_date>=xx and stat_date<=xx 就可以查询出应用最近两个月总的请求量,但是按时间分表后, 就需要执行这条sql 两次从每个分表中查询数据,然后还需要写代码在内存中对相同的应用进行请求量相加聚合处理,这里只是一个简单的需求,面对千变万化的需求处理起来还是有一定的难度的,业务实现也较为复杂。 Druid 实时分析系统的简单介绍 Druid的目的是提供一个能够在大数据集上做实时数据消费与探索的平台,对普通的数据平台来说,数据的高效摄入与快速查询往往是一对难以两全的指标,因此常常需要在其中做一些取舍与权衡。如传统的关系型数据库如果想要在查询的时候有更快的响应速度,就需要牺牲一些写入数据的性能以完成索引的创建,反之,如果想获得更快的写入速度,往往要放弃一些索引的创建,就势必在查询的时候付出更高的性能代价。
而Druid刚好能够同时提供性能卓越的实时摄入与复杂的性能查询。这些都是基于其独到的架构设计与数据结构优秀设计实现的。 下面是Druid的架构设计与数据结构简单介绍 Druid 总体架构包含四类节点:
1.实时节点:即时摄入数据,以及生成Segment数据文件
2.历史节点:加载以生成好的数据文件,以及提供 数据查询
3.查询节点:对外提供数据查询服务,并同时从实时节点与历史节点查询数据,合并后返回给调用方。
4.协调节点:负责历史节点的数据负载均衡,以及通过规则管理数据的生命周期 机群包括的外部依赖:
1.元数据库:存储Druid集群的原数据信息,比如Segment的相关信息,一般用MySQL或PostgreSQL
2.分布式协调服务:为Druid集群提供一致性协调服务的组件,通常为Zookeeper
3.数据文件存储库:存放生成的Segment数据文件,并提供历史节点下载。对于单节点集群可以是本地磁盘,而对于分布式集群一般是HDFS 或NFS 数据通过实时节点(实时)或者索引节点(批量)发送到Druid集群后,实时节点对实时数据进行消费,然后生成一个个Segment数据文件,并周期性的合并成一个大的Segment文件上传到数据文件存储库,批量的数据会直接上传到数据文件存储库,同时查询节点会相应外部的查询请求,并分别从实时节点与历史节点查询到的结果进行合并后返回。每个节点干什么事,提供什么服务,都很明确清晰,也方便扩展,提供高可用。 Druid 的数据结构DataSource与Segment 1.DataSource:
类似RDBMS中的表,结构如下
时间列:表明每行数据的时间值,这个列是数据聚合与范围查询的重要维度
维度列:用来标识数据行的各个类别信息,如应用、位置等
指标列:用于聚合和计算的列,如请求量、曝光量等 无论是实时数据消费还是批量数据处理,Druid在基于DataSource结构存储数据的时即可选择对任意的指标列进行聚合操作,该聚合操作主要基于维度与时间范围两方面: 同纬度列做聚合,所有的维度列的值都相同的时,这一类行数据符合聚合操作,比如 在一段时间类,收到了广告上报的曝光数据 appId =1, positionId=1 都是相同的,Druid 会对该数据进行预聚合,如收到收到1000条这样的曝光数据,Druid 系统中只会记录一条 数据 :
appId positionId exposureTimes
1 1 1000
这样能大大减少数据量的,增加查询效率。 对指定的时间粒度的值做聚合:上面同纬度列做聚合是对一段时间,这里可以指定时间,如1分钟、一个小时、一天等,可以根据需求来做 2.Segment
DataSource 是一个逻辑概念,Segment是数据实际物理存储的格式,Druid通过Segment实现了对数据的横纵向切割操作,Druid 将不同时间范围内的数据存储在不同的Segment数据快中,按时间范围查询数据的时,仅需要访问对应时间段内的这些Segment 数据块,而不需要进行全表数据范围查询,这使效率得到极大的高。 看到DataSource 和 Segment 结构设计是不是想到了RDBMS中数据库分区表结构设计呢?DataSource 是一张表,而Segment 代表表中一个个分区。Druid 高效的原因摄入数据的时候就对数据进行了预聚合大大减少了数量,在查询的时候通过查询节点发起请求,查询节点会通过时间范围找出对应的Segment 及存储该Segment 的历史节点和实时节点,并发的向这些节点发请请求,并对结果进行合并,假设需要查询的Segment 分布在3台机器上,那么就有3台机器为你处理请求,而且Druid是内存为王的查询分析系统,也就是说,当向这三台机器发起查的时候,如果数据在内存中,那么计算速度是相当快的,如果不在内存中,会先把数据加载到内存中并进行计算,多级缓存这是架构中设计提高吞吐量常见的技术。