专栏名称: InfoQ
有内容的技术社区媒体。
目录
相关文章推荐
新浪科技  ·  【#特斯拉为Cybertruck进入中国做准 ... ·  昨天  
新浪科技  ·  【#无创血糖手表靠谱吗# ... ·  3 天前  
新浪科技  ·  【#Steam季票规则更新##Steam要求 ... ·  3 天前  
51好读  ›  专栏  ›  InfoQ

QQ 空间社交广告系统技术架构实践

InfoQ  · 公众号  · 科技媒体  · 2017-07-14 08:00

正文

作者|冯启航
编辑|小智
QQ 空间的在增值营收服务上探索了多年,本文将展示负责增值服务体系的后台工程师如何在众多增值业务需求面前找到最合适的技术架构的支撑这个年入几十亿的产品,以及如何利用好大数据为增值营收带来新的增长引擎。

注:本文整理自 QCon 2017 北京站上的演讲,原题为:《QQ 空间平台百亿级流量的社交广告系统海量实践》

QQ 空间业务背景

空间里的广告除了一些效果类的展示广告外,大部分都是我们自己做的,比如有品牌类展示广告,这是我们 QQ 空间独立的 APP,会放一些像 OPPO 这样的品牌广告,还有品牌自身做的推直播、黄钻收入的广告,大广告主题和内部广告主题的问题是我们要解决的。

QQ 空间业务指标 QBOSS,取这个名字是定位于 Qzone 业务支撑系统,它每天日常有三百亿左右的流量,流量访问是很大的,QQ 空间等产品接入广告渠道有十百个,日常峰值 40 万每秒,性能要求高,我们的要求是整个计算耗时要在 50ms 内。

海量服务基础架构建设


做技术架构之前,先挑一些核心功能来看。首先要建立渠道的概念,这是很规范的管理。另外作为平台性来说,防止对用户进行骚扰,重复看过的广告还出现这是不允许的。再是定投,不可能什么广告都是全可见的,这也是很多做算法,做数据挖掘可以发挥的空间。第四,我们的客户系统是在播放端和广告主之间的一个桥梁,播放端不同渠道有开发诉求,广告投放这边广告的一些核心投放逻辑要实现,是排期性的广告系统。

定义秩序,中间核心是广告,根据广告的业务特点分了四个维度。左边这个就是广告位,这是很简单的事情,针对的角色就是做广告主的人。右边体现的是 QQ 空间方向,体现的是产品的运营导向,防止骚扰运作等等。最上面的方向是真正用户能够感受到广告体验的,资源分为两部分,一个是数据,比如这个图片是什么样子,视频是什么样子,这是素材问题。还有一个很值得的说的,对开发者来说我们给他一个展示模板的定义机制,能够支持开发者在客户层上面制定自己要的是什么样的逻辑,自己去开发。第四部分是对下面的用户细分,广告来了要给更合适的用户,数据上来说就是用户画像和号码包。

再讲讲腾讯通用的技术积累。经典的三层技术层里,接入层有 TGW WNS TSW 都使用的接入的方式,是比较线程可用的。中间这层特别 SPP 是腾讯内部最广泛使用的多线程模型服务框架,把网络通信相关的功能都已经收归了。还有一个同步中心,这是我们自研的一部分技术选型,这部分量级产品现在是深圳、上海、天津三地同步服务的,就涉及到数据层面同步问题,都抽象成一个服务建设出来做同步中心。还有是我们用的比较多的是 SSVR,它类似于一种队列型的服务,但是不像大家用到的云队列服务,我们是一个基于本地流水的服务,这个简单可控,实践证明这么多年用下来没出什么问题。

存储层研究比较多,首先 CKV 是最广泛使用的产品,CDB 是在 MySQL 上建立起来的 Cloud DB,Redis 用的也是比较多,TDW 是针对海量数据做的腾讯数据库。左边是一些系统或者组件,比如织云是我们的运维门户,L5 是做负载均衡的,罗盘是报表,因为我们广告系统用的比较多,DC 上报是分布式海量数据上报的收集系统,神盾做推荐的。那我们搭一个海量系统还需要做什么事情,除了设计之外,用它来凑一凑,海量系统就比较靠谱了。

整个广告系统麻雀虽小五脏俱全,很多服务过了三年都没法看了。我划分了一下,在线服务有策略中心、用户中心、数据中心,还有离线处理主要把用户的数据处理上去。主要介绍三个核心服务。

策略中心是很杂的部门,满足了广告系统的中控,主要是一些逻辑。

用户中心服务 DMP,一个部分是像左边这样,我们去搜集很多平台相关的活跃特性,比如你是不是黄钻,是不是登录活跃用户,把这些数据建立成标签,广告组就可以选出标签实现定投。还有一种是号码包方式,腾讯内部还有很多做数据挖掘的团队,包括数据产生,腾讯的业务实在太大了,很多的数据产生方不能都来我这里,必须用号码包的方式组织起来,这个用的比较广泛。

最开始最简单的架构就是这样。对外服务,提供一个协议是不是这个用户群的,是就回答 YES 不是就 NO,就是做了一个匹配逻辑,数据就很简单,把号码包的数据用户的数据存进去就解决了,这是最简单最开始的架构。

但是遇到了一些问题,一个是 DMP 要做强大,tag 数据一定要多,年龄、性别、装扮活跃、登录时间次数都是 tag 格式,tag 来源很多,很多的数据团队并不一定把数据放在你这个地方,另外更新频率也不同,就算是给你离线缓存权限,存整个平台的数据对客户系统来说也是很大的负担。成本还有开发效率,做这个系统的时候人力成本有限制,不像有的广告系统的团队专门做 DMP,我们这里只有一到两个人开发做这个。还有内存存储成本,存储的选型只能用内存,但是内存价格太高了,那这几百个指标要多少数据?

第一个问题,我们怎么提高用户画像 tag 的建设效率。腾讯内部现在还是这样做的,比如要做年龄和性别进来,一定数据存进来取一个名字,这样每增加一个 tag 效率是很低的。后来我们决定,放弃这个结构,按 ID 来划分,每增加一个 tag 增加一个 ID 是很简单的事情,ID 针对哪些 bit 位也是比较好映射的,比如有 64 位上去,再上去就是 128 了,反正编号编好,有序列号的,每一个 tag 要新增,就分配一些地方,我新增一堆 tag 没有工作量只需要分配协议。

还有是增加一个适配层来处理数据来源,有很多团队有数据,但是没有渠道扩大用户,我们把判断用户的权限开放。Adapter Server 是只要满足协议,把逻辑写好你自己来开发就好。

第三个问题是号码包定投,一开始我们想的也比较简单,存一下用户在哪个号码包里面,每次访问的时候拿这个数据判断就行了,看起来很简单很容易理解,但是实践的时候会发现缺点。投放难度是很大的,广告主投放一个五千万或者一亿的号码包,他需要把这个号码包所有用户的数据都拿出来读一遍写一遍,一个投放操作会影响在线的服务,因为要改在线的数据,在线的容量也会受到波动,广告主什么时候投放号码包也不确定,投放几个也不知道。

很大风险是投放一个等待时间又长,并且影响你的在线服务。我们有三个地方的服务,深圳上海天津,如果你在深圳投放还要同步这个服务到上海和天津。存储回收也比较麻烦,很多号码包跟着广告走的,广告一旦下线,号码包意义就不大了,很难回收它,你只能把这个号码包拿出来再更新一下用户。我们以前做过被动的更新,当用到这个用户的时候再拿出来检查号码包,这是非常被动的。

解决这个问题,我们用了 QZone 自研的存储利器,叫好友参与系统,非常适合号码包的 topic 存储。我们认为 topic 是个主题,号码包就是一个主题,用了号码包的都参与到这个主题中来,比如以前最火的 QQ 农场,你可以看到有多少个好友在玩农场,比如上千个好友都要看他是否在玩农场,这是非常大的计算量,于是我们就做了这个存储系统,可以根据存储系统的数据结构需求,把顺序的号码包处理成一个 Btree 树结构,用 tmpfs 处理这些号码包,使得每个 btree 文件就是可见的包,可视化的。我们的同步也很简单,原来需要跨地域,现在都是可视化操作了。

数据中心服务难点,主要管理用户的广告反馈数据。广告系统里面,数据中心和其他的和 UGC 很大的功能不同是,是读多写多模型,比如一次广告曝光,曝光之前需要看一下这个用户有没有看过这个广告,就需要读一次,如果觉得这个用户能够被曝光,就要写一下曝光记录,读和写的频次都是很高的。比如我发表一个说说相册,一般来说都是读的情况很多,写的情况相对很少。另外还是需要异地服务接入,数据同步问题也是,因为量大了,就容易堵塞通道。

数据中心服务架构剖析,每一个地区是这样一个架构设计,首先结构上是简单的逻辑服务, CKV 存储曝光点击记录,在逻辑读写命令是分开部署的,代码是一起的。另外做了旁路流水,每次写的时候要做很多事情,比如要统计广告的曝光点击量、点击率,第三方监控,在你这里投广告到底有没有投放需要统计一下,这些需求是很慢的,还有自己的一些统计功能,包括还有同步操作到另外两地都是很慢的,这个绝对不能放在在线的写操作里,写操作只能做关键操作即写 CKV。s_server 起到了一个队列作用,很快地接收数据值写到本地文件里去,另外再起一套进程读文件,按需跟通道通信,后端慢的服务也是按需服务的,只要跑得过流水产生的时间就行了。

我们在统计数据做了两个通道,左边是腾讯公司层面做的一个,是基于用户维度,用户实际曝光和点击哪些广告,在罗盘系统上做出一个统计报表。我们自己做了一个统计的数据,根据广告 ID 的维度做,不想再处理很大量数据的问题,我们不关注用户信息了,只关注广告 ID 的质量,就可以合并写操作,数据量、访问量减少,很简单的数据统计就可以把这个报表生成。两个通道两个逻辑,得出的数据是一致的,这个报表的数据就是很准的。

异地同步通常先对比一下通常的功能产品的模型,一般都是三地读一地写,比如你要看照片三地都可以看,你要发表一个照片一定要先接入到深圳,然后再同步到上海和天津。它比较简单,要考虑时序性,如果哪个操作失败了要重试,一定会堵塞通道。我们一定是要多读多写的,在你还在同步过程中,第二次请求已经过来了,比如在上海点了一个广告,本来不会再次出现了,但是还出现了,因为数据还在深圳往上海赶的路上。所以需要同步起来,三地写、三地读就要建六个通道,比一般的产品同步量会大很多,因为它强调的是一致性和时序性。

根据这个我们大胆做了一个不做堵塞通道的同步逻辑,我们敢这么做,而且我们只同步一些信息,比如我在深圳点了一个广告,我并不告诉你深圳存的是什么,上海同步的是什么,只告诉增量信息,因为很多渠道的接触方式也不一样,最后上海天津的存储容量都不一样。这样做,假如通道有一些故障会形成三个孤岛,最大的问题是假如用户在上海点了个广告,下一次请求他又去深圳了,这个广告他又看到了,这种情况下,我们大胆地尝试不用考虑这个问题,实际验证一下,这样的用户按我们的统计,一天影响量才万分之五,我们就不这么纠结,这是比较有特点的异地服务。

平台海量服务运营能力,一是监控能力,接口级别监控,实实在在统计成功率和延时,用户端监控,真正看广告拉出来的延时,还有广告数据监控,广告有没有按时出现,点击率是否符合预期。二是服务质量容量,服务质量就是个容量问题,容量够了质量就好,容量不够质量就不好。容量怎么来?这是广告系统会遇到的问题,广告计算的负载率会徒增,特别是平台类型的广告系统,不像效果性广告可以保持平稳的广告输出量,我们这儿不一样,比如有一些广告对你的系统有一个徒增或突降的状况。

每个广告的计算量都不一样,我们能做的事情,按照云计算的弹性能力来做这个事情,现在的情况下保持很好的服务质量还是有难度。至少对未来要承担的负债有一个大约的预警,你就要有模型去算,因为广告主都会有提前量,比如下午的广告上午就投了,不会马上生效,总有一个时间去检测负载是否足够。

还有是做高效能,就留个 5 倍、8 倍的 buffer,你留多了运维就压力很大,需要提高单机性能,我们一些监测的数据不会在服务器里编解码,除了广告分析数据,都是些 UDP 的协议,尽量简化这个逻辑操作。还有各种分离部署减少毛刺,比如数据中心读和写以及回收等等,一定不是分离的,为了避免有些广告突然间量上来,有一些操作会带来代价,平均下来三个九、四个九的成功率没问题,但是偶尔就是几分钟这样。

容灾,我们不会在单机上存一些跟用户路由相关信息,除非某个机器挂了,做负载均衡覆盖掉就可以了。包括设备管理,把高优先级、低优先级的设备分配管理,针对性做一些工作。支持城市级别容灾,这是经过像天津大爆炸一样的检验。还有是细节,所谓容灾,在一些很关键的地方都是可以覆盖住的,但是把你弄死的都是一些细节,重在细节,找短板。

广告系统 ROI 优化之路

再讲一下广告系统 ROI 优化之路,这是我们走过的弯路。走 ROI 就是推荐算法,包括和腾讯内部合作做一些事情,做完之后可以看看我们做的一些事情。首先在 ROI 优化前先要找准自己的瓶颈,我们做推荐算法,量级并不大,因为都是大业务的需求,可能广告里就五个、六个,不大于十个的广告,但是效果是很大的,甚至会经过初选、细选,复杂度都不一样,真的可以做到千人千面。需求量也不稳定,但是广告质量是可控的,因为广告主离我们比较近,我们了解他们的需求。

做了三种尝试。第一种是最开始走的弯路,有用户进来通过各种方式查数据,查在线的优化,会发现就算你知道用户喜欢哪一类广告,但是现在的库存里面没有这类广告,你没办法的。第二种方式,同样一个项目广告通过更多渠道去做,可能这个广告的用户群并没有在这个渠道上投,他去了另外一个渠道也可以做,对于广告主来说投放的代价是很大的,因为每个投放会带来开发成本和投放成本增加,每个渠道都是不一样的。

第三种是非常有用的方式,还是渠道给你,但是你不能再用一个广告了,必须要设计多个广告进来自己跟自己竞争,不同点在于广告 A 投的是这个用户群,广告 B 投的是另外的用户群。让用户投票,二三十分钟就可以得出每个广告的点击率,让点击率高的广告渗透下来,起到广告主和用户间的沟通桥梁,你做的工作好坏用户会给你反馈,这个是刺激到广告主要去新做一个广告。

ROI 另外一些很重要的功能点就是负反馈。比如有的人看广告七次都不会点进来,你给他投放再多次他也不会点,他选择性地忽视了,这部分人群不要给他出广告,对他来说体验也好了,对我们来说收益上也没什么损失。还有是频率限制,流量出来后并不是马上消耗完,平稳地在一天或者更多天消耗完。深圳发现一个好处,第三方投放的时候,因为他们往往不太知道流量,等到网站顶住了的时候,流量消耗完了,广告主不知道我们 Qzone 的流量有多厉害,但他肯定知道系统能顶多少量,让我们给他频率限制住。

还提供一个工具叫 QBOSS 人群分析统计,你投完广告之后我们会分析广告投放地好还是不好,选一组特征值,曝光人群里占特征值比例有多少,点击人群占百分比有多少,如果两个持平了,可能说这个在广告受众里不是很明显的东西,如果点击比例高于曝光的比例,这就是很正向的事情,你后续投这类广告的时候就要优先投这部分人群。我们提供的只是一种工具,一个渠道让你做个正负的反馈,广告主的优化必须是你自己想办法做的事情,做的好就是百分之四百,做的不好还是百分之十几。

写在最后


整个客户层还有很多体现腾讯海量服务价值观的东西,比如动态运营、全网调度等等,都在用,我不再赘述。

最后讲点心得,技术价值一定要体现在业务上面,我们开始做的广告系统,比如三大系统听起来很朴素,但是能解决业务问题就是一个好的东西。还有做职责识别,我们把一个广告系统分成一个大的方向,每个大的方向有它的职责问题,抽象一下也就能满足大系统小做,把一个复杂问题简单化,比如用户中心只需要判断这个用户是不是用户群的,别的问题都不用管。

再是抽象一个层,可以解决很多需求问题,有些 tag 的识别是非常特殊的,但抽象一个层往往能解决很多复杂问题。善于在存储上做性能提升例如 redis 的成功,逻辑很简单,性能也非常好,包括刚才介绍的好友参与系统都能很快解决问题。

低成本,一上来内存做的成本高,可能考虑到其他的存储介质,看看有没有一些协议压缩等等,很多技巧大家都会掌握,但是我建议大家还是从业务角度上考虑问题,可能给你带来的是上十倍、百倍的成本节约。尽量做无状态的服务,能够保证你的负载均衡、一致性,一旦有状态真的要悲剧了。还有各种部署的分离,在一些小流量系统里这个有点绕,但是在海量系统里这个还是很有必要的。我们所有的架构设计都是依赖自己的数据经验的,但是在你上线后一定要通过数据验证它。做异地同步的问题也是,上线后到底少到什么程度,才能让这个架构继续工作。

作者介绍

冯启航,2010 年毕业于四川大学加入腾讯,负责 QQ 空间功能后台开发工作。负责建设了社交平台基础增值会员体系、个性化特权业务、营收广告系统、营销活动平台等海量服务。技术上践行海量服务之道和敏捷开发的结合,喜欢做技术驱动型的工作,挖掘技术在业务上的价值体现。2016 年主导了空间宠物 AI 机器人聊天项目,在人工智能领域从新开始。追求团队把算法和工程有机结合在一起,目标为导向让机器学习、人工智能真正走入应用场景。