本文为课程笔记,课程地址:计算广告学
参考资料:《计算广告 互联网商业变现的市场与技术》
常用的广告系统开源工具
由于书和课程比较老,有的技术现在可能不用了
广告系统架构模块众多、交互复杂,从头搭建并不容易。在大型互联网公司中,这样的广告系统可以精雕细琢,其中的很多模块也都可以进行专门开发。不过,对于初创型企业和变现业务方向尚需探索的企业来说,需要根据最小值原型(Minimum Value Prototype,MVP)的原则,低成本、短平快地搭建系统,然后在实际业务中进行快速迭代。幸运的是,开源社区为搭建广告系统提供了很多不错的工具,利用这些工具可以相当方便地搭建起一个广告系统基础骨架。一般来说,我们可以利用成熟开源工具解决底层通信、数据传输、负载分配等基础问题,从而将精力重点放在与业务逻辑相关的开发上。下图标示出了计算广告系统中经常用到的一些开源工具。
nginx
我们先从在线投放时用到的 Web 服务器说起。由于广告系统有高并发、低延迟的性能要求,Nginx(www.nginx.org)在多数情形下都是广告系统首选的 Web 服务器解决方案。Nginx 是一款开源服务器软件,兼有 HTTP 服务器和反向代理服务器的功能。其主要特点在于高性能、高并发和低内存消耗,并且具有负载均衡、高速缓存、访问控制、带宽控制以及高效整合各种应用的能力,这些特性使得 Nginx 非常适合计算广告这种并发很高的互联网服务。
Nginx 还提供了 fastCGI 这一与各种编程语言之间的通信接口,开发者可以很方便地将服务器的功能逻辑用 fastCGI 插件的形式实现,而无需关注响应 HTTP 请求的细节。在广告系统中,用 Nginx 作为前端 Web 服务器,而将广告投放机的功能用 C/C++语言实现成fastCGI 插件,是一个开发成本较低、性能又很不错的方案。实际上,这一方案已经实现了一个基本的广告投放机,从事最简单的广告投放业务,而其他模块和功能则可以根据需求逐步开发。
分布式配置和集群管理工具 ZooKeeper
由于广告系统的流量很大,单台广告投放机往往不能满足需要。在使用多台服务器的时候,会遇到很多诸如配置文件更新、集群上下线管理等分布式环境下的同步问题。ZooKeeper(zookeeper.apache.org)是解决这些问题非常有用的开源工具。
ZooKeeper 是为分布式应用建立更高层次的同步(synchronization)、配置管理(con-figuration maintenance)、群组(groups)以及名称服务(naming)的通用工具。它的基础原理是 Paxos 算法,而这一算法最早的工业界应用是Google 开发的 Chubby。在编程上,ZooKeeper 的设计很简单。所使用的数据模型非常类似于文件系统的目录树结构,简单来说,有点类似于 Windows 中注册表的结构,有名称、树节点、键/值对等,可以看作一个树形结构的数据库,可以分布在不同的机器上做名称管理。由于 ZooKeeper 并不传递计算数据而是传递节点的运行状态,所以运行负载很低。
对广告投放机进行集群管理是 ZooKeeper 在广告系统中的典型应用之一:由于某台服务器宕机或者新机器上线,Nginx 的负载均衡方案需要及时作出调整。显然,人工地维护响应时间较长,不可避免地会带来一些流量上的损失。利用 ZooKeeper 的 Ephemeral类型节点可以很方便地实现此功能。
由于在广泛使用的 Hadoop、HBbase、Storm、Flume 等开源产品中都需要用到ZooKeeper 进行分布式同步,如果把上述开源产品看作各种小动物,ZooKeeper 这一命名可以说非常形象。
全文检索引擎 Lucene
大多数广告业务在初始运营阶段并不见得需要一个真正的倒排检索引擎,不过当广告业务开始面向长尾广告主,广告库规模较大时,采用“倒排检索”加“排序”这样的两段式决策过程是必要的。然而,实现一个功能全面、效率较高的倒排索引并不是一件简单的事,并且由于其与核心业务逻辑关系并不大,也可以用开源方案来实现。在开源工具中,Lucene(lucene.apache.org)是比较常用的基于 Java 的全文检索工具包。Lucene 并不是一个完整的搜索引擎,但是针对计算广告系统的需要,它可以方便地实现全文索引和检索功能。Lucene 能够为文本类型的数据建立索引,其主要功能是替文档中的每个关键词建立索引。另外,Lucene 还提供一组解读、过滤、分析文档,编排和使用索引的 API。我们选用 Lucene,除了它的高效和简单外,还因为它允许用户对其中的关键环节自定义功能逻辑。
在 需 要 比 较 强 的 索 引 扩 展 性 的 情 形 下 , 还 可 以 考 虑 使 用ElasticSearch(www.elasticsearch.org),这是一个基于 Lucene 构建的开源、分布式、RESTful搜索引擎。设计场景主要是在云计算的环境中,能够实现稳定可靠的实时搜索,并具有良好的水平扩展性。
跨语言通信接口 Thrift
图中的各个模块之间广泛地存在数据交换,不过由于各模块需求的不同,有时我们会选用不同的开发语言来分别实现它们;或者由于开源工具的不同,最方便的使用语言也不同。为了方便在不同语言的模块之间实现调用接口,避免应用开发者过多地将精力放在底层通信上,开源社区涌现了若干个跨语言通信接口工具。我们以 Thrift 为例来介绍。 Thrift ( thrift.apache.org ) 被 描 述 为 “scalable cross-language services implementa-tion”(可扩展的跨语言服务实现),它有自己的跨机器的通信框架,还提供了一套代码生成工具,可以生成多种编程语言的通信过程代码。Thrift 有一种描述对象和服务的界面定义语言(Interface Definition Language,IDL),它提供了一种网络协议,使用这些对象和服务定义的进程之间基于这种网络协议彼此进行通信。Thrift 根据 IDL 的描述可以生成绝大多数流行语言(如 C++、Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript 等)的代码框架。因此,服务器端实现语言不会影响到客户端,这给复杂的计算广告技术平台不同系统之间的通信提供了很大的便利。
此外,Thrift 还提供了实践中非常有用的版本兼容性功能,即服务器端能在不影响现有的客户端的情况下增加数据结构、字段、服务方法和函数参数。这一特性使得大型工程中模块间的依赖性大为减弱,也能够显著降低开发成本。因此,我们建议在计算广告的系统模块之间尽可能采用 Thrift 这类工具封装接口。
数据高速公路Flume
计算广告这样的个性化系统由于并发很高,产生的日志量也非常大。在这类系统中,应该避免对数据做单点的集中式读写,而是尽量应该让数据的处理形成环形的流动,即由数据高速公路将线上日志准实时地送至离线或在线处理平台,再将处理结果存放在缓存中供线上决策使用。在这样的架构中,一个分布式、高吞吐率的数据传送通道至关重要。
在这类数据传输工具中,Flume(flume.apache.org)是比较常用的开源解决方案之一。Flume 是 Cloudera 提供的一个高可用的、高可靠的、分布式的海量日志采集、聚合和传输的系统,它支持在日志系统中定制各类数据发送方,用于分布式地收集和汇总日志数据。Flume 提供了从控制台(console)、RPC(thrift-RPC)、文本(text)、Tail 操作(UNIX tail)、日志系统(syslog,支持 TCP 和 UDP 两种模式)以及命令执行(exec)等数据源上收集数据的能力。同时,Flume 还提供了对数据进行简单处理并输出到各种数据接收方的能力。如果广告投放机采用 syslog 方式记录投放、点击等日志,可以很方便地通过配置 Flume 将日志传送到 Hadoop 上。
其他的相关开源工具还有 Scribe(github.com/facebook/sc…
分布式数据处理平台 Hadoop
图中的离线数据处理部分需要一个能够存储和加工海量数据的基础设施,实际上这也是大多数大数据系统都需要的平台。在开源的这类平台工具中,Hadoop(hadoop.apache.org)几乎是工业界的标准选择。Hadoop的核心架构主要包括
HDFS(Hadoop Dis-tributed File System,Hadoop分布式文件系统)、Hadoop MapReduce和HBase,其中HDFS是GFS(Google File System)的开源实现,MapReduce是Google MapReduce的开源实现,而HBase则是Google BigTable的开源实现。HDFS是一种易于横向扩展的分布式文件系统,提供大规模数据文件存储服务,支持PB级数据规模。它可以运行在上万台的通用商业服务器集群上,提供副本容错机制,为海量用户提供性能优秀的存取服务。计算广告系统里的海量日志文件等就是通过Flume之类的数据高速公路传送,最终存储在HDFS上,为各种离线计算任务提供服务。
Hadoop MapReduce是一种分布式计算框架,顾名思义,它由两个部分组成:Map和Reduce。Map是将一个作业分解成多个任务,而Reduce是将分解后多任务处理的结果汇总起来。在程序设计中,一项工作往往可以被拆分成为多个任务,任务之间的关系可以分为两种:一种是不相关的任务,可以并行执行;另一种是任务之间有相互依赖,先后顺序不能够颠倒,这种任务是无法并行处理的。MapReduce适用于第一种类型,庞大的集群可以看作是硬件资源池,将任务并行拆分,然后交由每一个空闲硬件资源去处理,能够极大地提高计算效率,同时这种资源无关性对于计算集群的横向扩展提供了最好的设计保证。为了降低MapReduce编程的复杂性,人们还开发了Hive、Pig[33,63]等开源工具产品,使用类似于SQL的脚本语言发起各种数据计算任务。
在广告系统中,Hadoop主要承担着离线数据的存储和计算需求,可以说是计算广告系统进行大规模数据处理不可或缺的基础平台。无论是受众定向、点击率预测还是基础的报表生成,都需要在Hadoop上进行大规模的数据处理。因次,关于Hadoop的原理和应用必须深入掌握。
特征在线缓存 Redis
无论是离线计算的受众定向标签还是点击率模型参数或特征,由于规模比较大,一般来说都无法直接存放在在线广告投放机的内存中,而是要用独立的缓存服务。在线用到的特征缓存有两个显著的特点,首先是往往只需要存储简单的键/值对,其次是大多数情形下需要支持高并发的随机读和不太频繁的批量写。在这样的需求下,Redis(www.redis.io)是比较合适的开源工具之一。
Redis 也是一种 NoSQL 数据库,它主要提供的是高性能的键/值存储(key/value store),采用的是内存数据集的方式。Redis 的键值可以包括字符串、哈希、列表、集合和有序集合等数据类型,因此也被称作是一款数据结构服务器(data structure server)。Redis 会周期性地把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了主从同步,具有非常快速的非阻塞首次同步、网络断开自动重连等功能。同时,Redis还具有其他一些特性,其中包括简单的 check-and-set 机制、pub/sub 和配置设置等,使得它能够表现得更像高速缓存(cache)。Redis 还提供了丰富的客户端,支持现阶段流行的大多数编程语言,使用起来比较方便。
在广告系统中使用 Redis,需要注意的一点是,当以批处理方式更新其中内容时,应避免对线上高并发的读请求产生影响,因此有时需要采用多次写入的方案。
流计算平台 Storm
Hadoop 能够处理的数据规模相当可观,但是处理的响应速度却很难保证。因此,在图 的在线处理部分,需要一种新型的、能够以数据流的方式对线上日志准实时处理的平台作为基础设施,在这类平台的开源解决方案中,工业界比较常用的是 Storm(storm.apache.org)。
广告中需要用到流计算的问题包括在线反作弊、计费、实时受众定向和实时点击反馈等。我们希望的解决方案是能够自动地处理各流计算模块间的通信和数据依赖,并能够在数据规模增大时自动进行分布式的负载分配,Storm 这样的流计算平台就可以为我们实现上述的需求。流计算的任务逻辑与 MapReduce 过程有些类似,熟悉Hadoop 编程的读者也可以比较容易地在 Storm 上开发应用。不过需要注意的是,流计算的任务调度原则和 HDFS 上的 MapReduce 不同,流计算是调度数据,让数据在不同的计算 节点间流动起来,而MapReduce 是尽可能调度计算以减少数据 I/O。因此,流计算从本质上讲并不是一个可以真正处理海量数据的框架,它的特长仍然在数据处理的响应速度上。
Storm 保证每个消息都会得到处理,而且处理速度很快,每秒可以处理数以百万计的消息,并且可以使用任意编程语言来做开发。另外,Storm 还可以直接部署在在新一代的Hadoop 计算调度引擎 YARN 上,这样可以非常方便地共享一个 Hadoop 集群的存储功能和计算资源。
其他的相关开源工具还有 S4(incubator.apache.org/s4)以及下面要介绍的… 的 Streaming 方式(Spark.apache.org/streaming)等…
高效的迭代计算框架 Spark
Spark(spark.apache.org)在最近几年崭露头角,作为一种新兴的大数据计算平台受到越来越多的关注,一些计算广告系统也开始广泛使用 Spark 平台解决一些需要迭代计算的问题。用 Hadoop 进行大规模数据处理在 Map 和 Reduce 两个阶段之间需要用硬盘进行数据交换,因此在需要面对多次迭代才能完成的任务时效率相当低。由于这样的迭代计算任务在计算广告中很常见,如文本主题模型、点击率预估等,我们非常需要一种更适合于迭代计算的框架。
作为一种新型分布式计算框架,Spark 的最大特点在于内存计算。Spark 的计算模型可以更加精简地描述等价的 MapReduce 模型,另外由于 Spark 的数据共享基于内存,因而相对于基于硬盘的 Hadoop MapReduce 批处理计算,其性能有数量级的提升。此外,Spark可以在一套软件系统上支持多种计算任务,除了传统的 Hadoop MapReduce 所对应的批处理计算之外,还支持各种机器学习算法为代表的迭代型计算、流式实时计算、社交网络中常用的图计算、SQL 关系查询、交互式即席查询等。这样,使用 Spark 就可以避免同时维护多套针对不同计算需求的系统,还可以避免不同系统之间的数据转储,大大减低了开发和运维成本。
虽然 Spark 可以在很多中等规模的迭代计算问题上表现的性能非常优异,但是由于大量数据的基础存储仍然要依赖于 Hadoop,在两个集群之间调度数据成为高效处理数据的 障碍。不过,与 Storm 一样,现在Spark 也已经可以直接部署在 YARN 之上,以“Spark on YARN”的方式与 Hadoop 方便地共享集群的存储功能和计算资源。
合约广告简介
感觉目前合约广告占比较低了,但是该数学问题在其他广告形态中可能出现
-
供给方:广告排期系统
- 帮助,媒体自动执行多个合同的排期
- 不提供受众定向、可以将广告素材直接插入页面
-
需求方:代理商
- 帮助广告商策划和执行排期
- 用经验和人工满足广告商质和量的需求
担保式投送与广告投放
担保式投放(Guaranteed Delivery, GD)
- 基于合约的广告机制,约定的量未完成需要向广告商补偿
- 量优先于质的销售方式
- 多采用前次展示付费(Cost per Mille, CPM)方式结算
广告投放机
- CPM方式必然要求广告投送由服务器完成决策
- 受众定向,CTR预测和流量预测是广告投放机的基础
- GD合约下,投放机满足合约的量,并尽可能优化各广告主流量的质(带约束的优化问题)
担保式投送系统的整体架构如图所示。在此系统中,在线投放引擎接收用户触发的广告请求,根据用户标签和上下文标签找到可以匹配的广告合约,然后由在线分配模块决定本次展示投放哪个广告。完成决策后,将展示和点击日志送入数据高速公路。这些日志一方面进入离线分布式计算平台以后,通过日志的整理,完成合约的计划,即确定在线分配算法的参数,再将分配方案送给线上投放机使用;另一方面,日志也送到流计算平台,在反作弊和计价的基础上,再对索引进行快速调整。可以看出,这一系统的核心技术是在线分配的算法策略与执行过程。
由于担保式投送需要用到人群标签或上下文标签,因此在广告检索的过程中也需要用到用户标签(user attribute)和页面标签(page attribute)这两个标签库,由于标签的生成过程与担保式投送本身的关系不大,我们将放在后面受众定向技术部分集中讨论。担保式投送需要用到的核心技术,最重要的就是在线分配。关于在线分配。除了在线分配以外,担保式投送还有另外两项主要的支持技术:流量预测和频次控制。
在线分配系统
供给与需求二部图以担保式投送为代表,可以看出在线分配问题有两个主要的挑战:一是要在量的约束下优化效果;二是要实时对每一次展示作出决策。直接在这两个要求下优化,会使得求解过程相当困难。因此,在在线分配问题中,一般将此问题简化为一个二部图(bipartite graph)匹配的问题。这里的“二部”指的是代表广告库存的供给节点(集合记为 I,其中某个节点代表的是所有标签都相同的流量库存)和代表广告合约的需求节点(集合记为 A)。
供给节点、需求节点和在线分配二部图的示例如图 11-5 所示。在这个示例中,下方的 6 个节点为供给节点,而上面的三个节点为需求节点。如果某个供给节点的受众标签能够满足某个需求节点的要求,就在相应的两个节点间建立一条连接边。我们把这个二部图记为 G=(I∪A,E ),其中 E 为 I 与 A 之间边的集合,并用 Γ(a)表示所有与需求节点 a∈A 相邻的供给节点的集合,而表示所有与供给节点 i∈I 相邻的需求节点的集合。我们的任务就是求解由 i∈I 到 a∈A 的分配比例,使得满足供给方和需求方的约束的同时,某个与广告效果相关的目标函数达到最优。
分配问题定义
其中表示供给方i的流量大小,表示将供给方i流量分配给需求方a的比例,表示将供给方i流量分配给需求方a的价值, 为将供给节点 i 连接到需求节点 a 的单位流量惩罚。
实际产品中常见的需求约束有两类:一类是预算、服务成本等的上限要求;另一类是合约量的下限要求。在后一种情形下, 为负数,需求约束实际上描述的是一个收益项的下界。
在线分配问题举例
在线分配技术并不仅仅适用于 GD 问题,其他典型的问题还有 AdWords 问题、展示广告问题、最大代表性分配(Maximal Representative Allocation,MRA)问题以及广告交易平台中的询价优化问题等。
1. GD 问题
在线分配的最典型应用就是 GD(担保式投送)问题。在此主要考虑按 CPM 结算的市场。在 GD 合约的情形下,由于按 CPM 售卖广告在所有合约都满足时,如果不考虑合约 a未完成的惩罚,收益是一定的常数。那么GD 的优化问题可以写成:
可以看出,GD 问题的优化目标主要在于更好地满足所有合约的要求,而不是优化eCPM。有时,GD 合约在未达成(under delivery)时会有相应的惩罚,在这种情形下,目标函数就不是常数了,可以引入惩罚项来改写上面的问题。
2. AdWords 问题
AdWords 问题,也被称为有预算约束的出价(budgeted bidder)问题,讨论的是在CPC 结算的竞价广告环境下,给定各个广告主的预算,整体化市场营收的问题。在这种情形下,公式中的目标函数和需求约束都有所变化,其对应的在线分配问题体现为如下的形式:
可以把这里的供给节点 i 具体想象成搜索广告中的一个关键词。于是,代表的是将关键词 i 的一次点击分配给广告 a 的期望收益,即广告 a 对关键词 i 的出价[7];为关键词 i 的总点击量;而 为关键词 i 分配给广告 a 的流量比例。AdWords 问题的优化目标是整个市场的收入最大化;而需求约束的含义是每个广告主的花费应该小于该广告主的预算。
Hadoop介绍
网上资料总结较好,可参考下面
MapReduce 与 分布式机器学习
在分布式机器学习中常用的统计模型有两种:指数族分布和指数族混合分布
指数族分布(Exponential Family)是条件概率服从某种形式的,有:高斯分布、泊松分布、多项式分布等。指数族分布的一个好处是通过最大似然(Maximum likelihood, ML)估计可以通过充分统计量(sufficient statistics)链接到数据,或者说得到数据的规律。这里的充分统计量(sufficient statistics)是指数族分布中的一个组成部分,一般来说就是模型的参数(如高斯分布的均值和方差)。
而当单个的指数族分布无法刻画数据的分布的时候,就要考虑多个指数族分布混合在一起的分布,也就是指数族混合分布,常见的指数族混合分布有:Mixture of Gaussians、Hidden Markov Models、Probabilistic Latent Semantic Analysis (PLSI)等。在指数族混合分布中, ML估计一般通过EM算法迭代得到。每个迭代中, 我们使用上一个迭代的统计量更新模型。而一般的 ML 和 EM 算法能够通过 MapReduce 过程较好地刻画
对于 ML 过程只需要一个 mapper 和 一个 reducer 即可,上面从 reducer 经过 model 返回到 mapper 的过程代表 EM 的迭代过程。这样刻画的好处使得在 mapper 中仅仅生成比较紧凑的统计量, 其大小正比于模型参数量, 与数据量无关;同时这样的流程可以抽象出来, 而具体的模型算法只需要关注统计量计算和更新两个函数。
但是对于需要迭代的算法,MapReduce 需要与 HDFS 进行多次交互从而导致性能不佳,而这也是 Spark 等框架致力于解决的问题之一。