从宏观角度聊聊广告系统

本篇文章会从宏观角度上聊一聊,一个功能完备的广告系统,需要哪些模块。首先来解释下,对于一个广告系统来说,怎样才算是功能完备。 我认为,最主要的一点是,要能够支持各种计费类型的广告投放。 常见的广告计费类型有:

  1. CPD:合约广告,把广告位直接包下来,因此在广告召回过程中不存在与其他广告竞价的环节,在广告投放过程中,会涉及到排期问题。
  2. CPM:按曝光数计费,可以再分为:
    1. 竞价CPM:竞价广告,广告召回过程中需要与其他竞价广告按照eCPM去竞价,价高者得。
    2. 合约CPM:合约广告,媒体方需要保证给广告主跑满合约中约定好的曝光量,在广告召回过程不存在竞价,但需要进行库存分配。在广告投放过程中,涉及到流量预测问题。
  3. CPC:竞价广告,按点击数计费,因为要换算成eCPM竞价,所以会涉及到CTR预测问题。
  4. CPI:竞价广告,按安装数计费,为了换算eCPM,需要CTR、CVR预测。
  5. CPA:竞价广告,按安装后的事件计费,同CPI。
  6. oCPM:竞价广告,按曝光数计费,详细可以阅读:《我所理解的oCPM》

广告系统架构图

上图是一个能够支持上面几种计费类型的广告系统架构图,可以划分为四大部分,下面依次介绍:

一、投放平台

后台投放系统

这是整个投放平台的核心。所有跟广告相关的创建、管理均是在这个系统上完成的。创建好的数据一般存入数据库,如MySQL,供其他模块使用。

广告上下线系统

广告主会设置预算金额,当跑满了之后,广告就应该下掉了,广告上下线系统就是一个定时任务,不断地去查询当前广告的有没有达到预算, 如果达到预算,那么就将该广告设置为已达到预算状态,这样就不会将该广告生成到索引里。

合约广告排期系统

对于合约广告来说,创建的时候,要进行排期,需要确认所需的流量资源是否充足。对于CPD广告,排期比较简单,因为不管未来的流量是多少, 它都是全部占用的,换言之,一个广告位在某一时间段只能被一个广告所占用。但是对于合约CPM广告,排期就会变得很有挑战性,因为涉及到流量预测问题, 需要我们根据历史的流量来预测未来的流量,以提供给广告主进行预定。

合约广告库存分配系统

因为合约CPM投放时,可以只预定广告位一部分的流量,所以会出现一个广告位在相同时段内,可以同时召回两个合约CPM广告,那么这两个广告具体选哪一个呢? 这就涉及到库存分配问题了。库存分配问题其实就是:根据广告还需要的流量,以及当前库存还剩余的流量,来进行最优的流量分配,使得所有广告都能得到所需的流量总量。 库存分配一般使用HWM算法来解,这个算法的原则就是,将流量优先提供给当前最难完成目标的广告。HWM算法的最终结果,是给每个广告输出一个播放概率, 广告引擎进行合约CPM广告选择时,按照每个广告的概率大小来随机选择。

合约广告其实是一个很有意思的话题,了解更多可以阅读:《合约广告(一):排期系统》《合约广告(二):库存分配》

索引生成系统

广告系统的流量一般都特别大,因此,在投放平台创建完成的广告,一般需要会构建成索引,来供广告引擎使用,以提高广告召回的效率,缩短整条链路的耗时。 生成的索引文件,可以放到分布式文件系统上,如HDFS、S3等。

二、广告引擎

业务网关

一般广告系统对外会提供多种协议的接口,如公司内部的APP会使用内部协议,对外部流量一般使用openRTB协议,业务网关的作用就是进行协议转换, 将对外提供的多种不同的协议,转换成广告引擎内部使用的相同的协议,然后再将广告请求发送给下游的混排服务。同样,收到混排服务的响应后, 需要将响应体转换成对应的协议,返回给广告请求方。

混排服务

广告引擎的核心服务。当收到业务网关的广告请求后,需要向LBS服务拿到地理信息,向DMP服务拿到用户画像。然后再向广告检索服务拿到符合当前流量的广告, 如果拿到的是合约广告,那么可以直接返回给业务网关。如果拿到的是竞价广告,那么还需要走一遍算法精排服务,拿到广告的eCPM,进行排序后,再返给业务网关。

DMP

用户画像服务,属于基础服务,这里不再展开。

LBS

地理位置服务,同样属于基础服务,这里不再展开。

广告检索服务

从广告索引文件中,检索出符合当前流量的所有广告。如果检索到CPD广告,那么直接返回即可。检索到合约CPM广告,那么需要根据库存分配系统计算出的播放概率, 随机选择一个返回。除此之外,对于竞价广告,为了防止检索太多的广告到混排服务,所以一般还要再走一遍算法的粗排模型,按照算法返回的优先级, 选择固定数量的广告返回给混排服务。另外,有的广告可能会设置播放频次等各种各样的限制,所以广告检索还需要从缓存中读取广告的播放信息, 以便判断该广告是否可以被召回。

广告检索在广告系统的工程层面是一个核心的问题,关于更多内容,可以阅读我之前写的文章:《由浅入深的聊聊广告检索》

算法粗排服务

对检索到的广告进行一次粗排,得到广告的优先级。粗排一般来说不是精准的,所以这一步一般并不是进行CTR、CVR的预测,更多的是根据当前广告的表现, 进行一个简单的预估。因为粗排的广告输入数量一般比较大,所以对粗排的要求是,可以不精准,但是速度必须快。

算法精排服务

混排服务进行竞价广告排序时,需要获知每个广告的eCPM,算法精排服务就是用来预测eCPM的。精排顾名思义,就是可以得到精准的排序。有人会问, 既然我们有精排,那为啥还要在广告检索中,进行一次粗排呢,把所有广告都走一遍精排岂不是更完美?这种想法当然是很理想的,但现实就在于, 精排服务一般都需要走模型,比较耗时。如果每个广告都走一遍精排,那么整个广告引擎的耗时就很变长很多。所以需要先走粗排,过滤掉一部分广告。

曝光、点击监测服务

广告到达客户端后,当用户有了曝光、点击行为,需要对该行为进行上报。曝光点击监测服务的作用就是对客户端发生的曝光点击进行监测, 一般会写两份数据,给缓存写数据,用于检索服务进行频次判断。给消息队列写数据,用于后续的报表生成。

三、归因系统

关于广告归因更详细的业务讨论,可以阅读我之前写的文章:《聊聊广告归因》

归因点击服务

对于CPI、CPA广告,当产生点击时,客户端除了向曝光点击监测服务上报外,还会向归因点击服务进行上报。归因点击服务会把归因链接中的宏参数替换成真实值, 对于不同的流量场景和订单类型,可以选择将归因链接通过http 302跳转的方式返回给客户端,让客户端完成归因上报,也可以选择归因点击服务端自己直接上报给归因平台。 关于归因业务,目前业界并没有一个统一的协议标准(比如广告请求就有openRTB协议),所以各家归因平台的归因参数都各不相同,归因点击服务需要分别对接、支持。

三方归因平台

这是这个架构图中,唯一一个不属于广告系统的模块,所以使用了虚线表示。客户端会把安装激活时间上报给三方归因平台,归因平台完成从安装到点击的归因后, 再把归因信息通过媒体方提供的接口,回传给媒体方。

归因回传服务

用于接收三方归因平台回传的归因信息。同归因点击服务一样,各家归因平台回传的归因事件中,能够支持的参数也是不同的,所以归因回传服务同样需要 与不同的归因平台进行对接。

四、大数据模块

广告相关的数据,如曝光数、点击数、归因数、CTR、CVR,都是需要通过报表查询。大数据模块从消息队列中消费数据后,经过ETL流程, 将日志数据存入OLAP数据库(如clickhouse)中,供报表进行查询。我本身是服务端工程师,对大数据的了解有限,因此大数据这部分也就不再展开聊了。