程序员最大的幸福是看到自己的代码跑在千万人的设备上,程序员最大的不幸是去维护千万人设备背后的老代码。腾讯新闻,是一个有着十多年历史、海量用户规模的经典业务,其背后的系统走过了门户时代,走到了推荐算法时代。 随着时间的推演,老旧架构面临着那些经典的问题:可用性差,服务不稳定;扩展性差,开发周期长,迭代效率低;200 多个代码仓库,300 多万行代码,编程语言、协议混用…… 叠加上推荐算法的时代命题,如何对腾讯新闻的推荐架构做升级成了业务进一步发展的内在要求。本文从业务场景介绍入手,详细介绍了腾讯新闻推荐架构升级过程中的目标设定,架构设计和实践过程,值得仔细品阅,转发点赞收藏一键三连。
我们先来简单回顾下腾讯新闻的发展历程,腾讯新闻源于03年成立的门户网站腾讯网,成立之初,抓住了中国互联网崛起的东风,位列四大门户(搜狐、新浪、网易)之一;2010年伴随着智能手机的普及,也抓住了移动互联网普及的浪潮,第一批推出了腾讯新闻的客户端,经过了一系列交互和内容的创新,于2014年移动端的用户数更是达到了峰值的 DAU2.5亿,位列资讯类 APP 第一位,一度也达到了应用总榜的第一,这是截止到当时唯一触达榜首的资讯类 APP,由于这些傲人的成绩,腾讯新闻在2015年强势拿到了腾讯集团的“名品堂”,该奖项授予那些曾经影响到腾讯集团发展历程的里程碑式的应用,应该算是腾讯新闻最高光的时刻,时至今日腾讯深圳总部大楼上高悬的还是腾讯新闻的 logo:
万事万物的发展,基本都要遵循生命周期的规律,一个互联网产品也会遵循一定的发展曲线,经历了2015年的高光时刻,自身业务逻辑的膨胀以及外部环境的变化,腾讯新闻也迎来了生命周期上的阵痛期,业务形式和技术架构都要求拥抱变化。
2.1 发展阶段
谈到腾讯新闻的业务,我的理解里面大致将他划分为三个阶段:
第一个阶段:我把它称之为以类目为索引的橱窗式内容陈列阶段,这也是所有门户网站的内容组织形式,就像一个大的“内容超市”,你会看到各类内容,按照一个大的分类体系(按照颗粒度不同少则几十大则几百上千)来组织内容然后呈现给用户:
分类体系示意
这个阶段的持续时间,我们对应到腾讯新闻发展的历史进程之中,大概是在2003-2020年,但是我认为这个阶段在2015年之前是比较成功的,2015年之后就有所变化,为什么会这么说,我个人感觉这跟互联网内容生产的模式息息相关,在2015年之前互联网的内容生态呈现如下的特点:
因而各家门户之间比拼的更多的是运营的功力,如何能够更快的覆盖热点,能够提供独家内容的消费渠道。腾讯新闻在内容运营方面是符合这个时代的特点的(“打造精品,自我变革”),同时发力移动端也比较早,因而在这个阶段获得了快速的发展。
第二个阶段:我把他称之为个性化引擎驱动的瀑布流阶段;这个阶段的开始源于个性推荐资讯类 App 的盛行,从时间节点上看,我觉得应该在2015年左右,但是腾讯新闻真正将个性化分发能力作为一个重点发力的时间点大概在2020年。这个阶段的主要特点是:
由于信息量陡增,原有新闻擅长的精细化运营的模式,受到了极大的冲击,所以在2016-2020这个时间段,新的内容生产模式跟新闻原有的运营方式以及组织架构产生了摩擦,应该算是一个阵痛期,陆续涌现出了一些问题:
从2021年开始,虽然当时业务上还存在一些摇摆,但是从架构上我们确立了以推荐引擎驱动的分发模式,因而也正式开启了长达2年的系统架构升级之路。
2.2 业务分类
虽然整个腾讯新闻里面场景众多,从细分来看超过了400个场景,但是从底层本逻辑来看,我们可以将所有场景总结为两大类:
个性化推荐的场景:
该类场景的特点是:所有系统的请求由用户主动触发,由于用户的作息和使用手机的习惯存在差异,因而请求数量存在周期性规律,同时由于所有请求由用户主动行为触发,因而活跃用户占比较高。同时,为了提升用户的消费行为,我们也会倾向于使用更加复杂的模型,同时由于热点事件的热点事件影响大,业务场景多,策略的复杂度高,整个系统以消费深度和留存作为主要的优化目标。
个性化推送的场景:
该类场景的特点是:请求通过系统触发,覆盖的用户量级极大,不活跃用户占比高超过正常水平,计算密集度高 QPS 超过数十万,需要兼顾时效性和个性化,以拉活和拉新为主要目标。
在展开架构升级的过程之前,我们先来思考两个核心的问题:
1、当我们的产品处于一个高频、多变的迭代之中的时候,我们如何才能保持我们系统架构的生命力?
常见的架构设计问题
各个场景的产运是路上行驶的各种规格的车辆,我们的系统就是一条条的公路,优秀的架构升级不是要大家不开私家车改坐公交车(放弃业务逻辑独立的系统统一),也不是给每辆私家车修建一条专属道路(业务主导系统建设,成本高昂,养护不易),而是建设一条公共的高速公路(逻辑复用),合理架设桥梁,安置信号灯(控制收口),让各类车辆,往来穿梭,并行不悖(高并发)。
2、判断一个系统架构好坏的评价标准是什么?
可用性:主要是指一个系统在满足功能要求的前提下,在一定时间内正常运行的程度,我们可以用如下的公式来定义:
可用性是衡量一个系统健康度的最基础的指标,可用性存在问题,其他指标也就无从谈起。
可扩展性:主要是指系统处理增加的负载、用户数量、数据量或复杂业务逻辑的能力,一个扩展性好的系统架构,在应用上述问题的时候,不需要进行频繁的重构或者替换。可扩展性是系统架构能够长期有效运行并满足未来需求的关键衡量指标。良好的扩展性设计使得系统能够在不牺牲性能和稳定性的前提下,适应不断变化的业务迭代需求。
可运维性:主要是指系统在运行过程中的运营成本、以及进行维护、升级以及 bug 修复的难易程度,通常包含几个方面的要求:整个系统的可解释性、可测试性、文档完整度、配置化程度、自动化、容错性以及可监控性等。
了解了前面提到的两个核心问题,我们带着这两个核心问题,来观测升级前的腾讯新闻整体的架构:
老的架构示意
我们可以看到腾讯新闻是一个迭代非常频繁的业务产品,同时原有的架构延续了门户网站时代:水平分层,场景自治的设计理念,该设计在早期以运营为主体的阶段,给了产品和运营团队极大的灵活性,但是到了当下个性化引擎驱动的时代,就暴露了很多的问题,我们从上面提到评价系统架构的三个标准层面去看,可以看到以下的问题:
为什么老的架构适合个性化驱动的业务诉求,个性化引擎由于引入了模型打分,为了使得系统能够快速的逼近当下的最优解,往往迭代速度会更加的迅速,链路也相对会更长;同时,新闻是一个发展超过了20年的老业务,在发展过程中累积了相当的历史债务,主要体现在如下方面:
4.1 目标
有了前面的铺垫,我们可以用一句话,来概括我们架构升级的目标:在保证业务逻辑独立性的前提下,实现架构的复用,提升系统架构的健壮性(保证用户体验)、可扩展性(提升迭代效率)、可运维性(降低维护成本)。
这里面有个非常核心的前提,“保证业务逻辑的独立性”,为什么这个前提很重要,因为我们从历史经验来看,很多公司技术路线演进过程中,是牺牲掉了部分业务逻辑独立性换来的。比如,早些年业界提出了“大中台,小前台”的中台架构理念,但是随着时间推演,业务蓬勃发展下,业务逻辑独立性的诉求逐步增加,中台逐步成为了限制业务独立发展的枷锁,这也就不难理解最近,业界又开始拆中台的风潮了。
于我个人而言,我不反对建设一个技术中台,但是这里面有个很重要的原则,就是我们要来定义什么样的组件适合成为一个中台,以及业务和中台的关系如何界定。譬如说:数据资产管理、容器平台、机器学习平台这些作为中台,基本是可以达成共识的。但是长在这些公共组件之上的推荐引擎部分,能不能拿了作为中台,很多公司在这些方面有不同的看法,我个人认为要结合业务的发展阶段来看。如果一个业务早期,需要快速验证业务模型,快速试错,当然接入一个统一的引擎中台,无疑是最快速、成本最低的做法;同样业务如果处于生命周期的中后段,处在一个维稳状态,没有太多的迭代前提下,也比较适合中台这种集中式托管的方式。但是如果这个业务正处在一个快速发展的上升期、以及平台期亟需寻找第二增长曲线的阶段的时候,捆绑在中台,无疑对于业务的迭代效率就会产生制约。这个阶段中台的角色作为一个孵化器往往是比较合适的,给业务提供一些基础的组件,同时类似开源社区的方式,允许业务自己维护自己的代码版本。
4.2 路径
有了上面的认识之后,我们如何来推进我们的架构升级?我们先要做什么,后要做什么?
这里面我想提一个可能在推荐系统架构设计里面不太常被人提及的概念”领域驱动设计(Domain-Driven Design, DDD)”。
领域驱动设计(Domain-Driven Design,简称 DDD)是一种软件开发方法论,它专注于创建一个以业务领域为核心的软件模型。DDD 由 Eric Evans 在2004年提出,其核心思想是通过领域模型来定义业务和应用边界,确保业务模型与代码模型的一致性。DDD 的目标是帮助开发人员更好地理解和建模业务领域,将业务领域的知识和逻辑融入到软件设计中,从而提高软件的质量和可维护性。
为什么这里要提这个概念,因为我们在实际工作中发现,很多系统设计是缺乏底层理论支撑的,只是为了解决单点的问题。这样随着业务迭代,日积月累,必然导致积重难返。我们架构设计首先需要理解底层的业务逻辑,这跟 DDD 的理念不谋而合,因为 DDD 的第一步就是领域建模。
领域模型是 DDD 的核心,它描述了业务领域中的概念、实体、关系和业务流程。通过领域模型,我们可以将业务领域的知识转化为计算机可理解的语言,实现业务逻辑与技术实现的统一。
所以我们系统重构的首要问题,是面向数据要素建模。
数据基础决定上层架构,历史债务治理,首要进行数据治理,数据收敛带动架构统一推荐系统里面最核心的数据要素是什么:用户、内容、特征、策略。
数据收敛带动架构融合
我们希望围绕推荐系统内部的四个核心要素,进行统一的平台化治理,将数据要素的读写进行统一的收口,然后在此基础上,按照推荐的漏斗进行一个微服务改造,提升系统整体复用性和扩展性,具体的执行路径如下图式:
演进路线
平台建设
为了实现整个底层数据模型的统一,我们花了接近2年的时间,进行了底层数据平台的建设,并推送了多个场景对底层数据依赖的统一,下面我们找两个有代表性的平台进行一个简单的展开,在建设这些平台过程中遇到的问题以及核心的思考。
5.1 索引平台
问题与挑战
XX平台架构
老的新闻索引服务,没有所谓平台的抽象。基本都都是按照分发场景对于内容池的要求(内容的质量、时效、安全等级、内容的分类),进行的离线加工,并且推送到在线的物理机进行在线访问的,主要存在以下的问题:
新的架构设计
新的索引架构
新架构的设计要点:
新架构的技术挑战:
应对措施
一致性问题:
参考大数据处理的常用的一致性架构 Lambda 架构,流批一体进行定期的校准。
Lambda 架构
Kappa 架构
性能问题:
采用了全内存的方式,支持多线程进行读写请求,同时结合业务特点进行了定制化的调优,比如:分片的方式、底层的数据结构。
1、数据结构的选型:
首先是底层数据结构的选型问题,我们如何确定底层的数据结构,需要结合新闻的推荐的场景特点:
选型的对比:
选型的原则:增、删、改、查效率稳定,简单可依赖。
2、拉链构建方式的优化:
单链
多链
对比
拉链长度跟性能的关系
最终我们选择多链作为我们底层的倒排构建方式:跨场景内容量级差异大,要闻 xxw,二级频道 xxx 万,线上稳定性优先,尽可能减少 pv 查询级别的复杂度,每天 xx 亿 pv,通过配置管理减少拉链无序扩张。
3、分片方式的优化:
term Hash 方式
doc 哈希
考虑索引服务本身对于性能和稳定性的极致要求,我们最终还是选择了doc哈希的方式。
4、分片数量的问题:
另外一个核心的问题:分片数量是不是越多越好?答案显然是否定?分片的多少对于一个系统性能的影响也是非常大的。
分片多:并行度高,单次请求效率高,追增量快;代理扇出大。
分片少:代理扇出小,召回效率高;并行度低,容量小,追增量慢。
分片数量
5、整个在线架构分层:
当新闻推动精品资讯战略,内容池由千万缩减到百万,单分片可以承载整个索引数据的时候,三层架构是否还具有良好的性能?
6、性能优化的收益:
场景赋能:
认知:任何技术的出现都是为了解决业务的问题,技术的优化必须贴合业务场景,面优于线优于点,路线正确优于细节正确。
1、个性化推荐场景:
传统的召回索引架构
场景业务特点:
传统架构的问题:
新的召回索引体系
优化成果:
2、个性化推送的场景
老的推送场景架构
老的架构问题:
新的架构
优化成果:
迭代效率问题:
在谈迭代效率问题,之前我们回头思考下,老架构发生的缘由是什么?答案显而易见,独立物理池的方式,给了运营对内容池干预的最大的灵活性,而且相互之间不影响。
独立池
完全去池化
逻辑池+统一索引架构
优化成果:
5.2 特征平台
特征质量直接决定了推荐效果的上限,特征服务是推荐系统最核心的基础服务。
老的特征链路
问题与挑战
新的架构设计
新的架构全景
核心能力:
解决的核心问题:
迭代效率问题。
原有的特征链路
存在的问题:
简化后的链路
设计要点(工程保证效率,算法关注效果):
这里面有个非常关键的模块,在线特征服务,它的效率直接影响到了整个特征迭代的效率,我们充分对比了业务主流的解决方案:
场景赋能:
认知:特征服务应用场景广泛,为了保证多场景架构的通用性,需要结合场景进行架构抽象、规范化治理。
我们结合前面抽象出来的两类新闻的核心场景,抽象出来了两套通用的架构解决方案:
个性化推荐场景的通用架构
双塔&&个性化推送场景的通用架构
优化成果:
主端、手 Q 插件、微信插件模型特征开发效率由之前周级别缩短至0.5天以内,提升了90%了;配置化管理,一次配置离在线同时生效;数据和抽取逻辑解耦,避免算法工程同时操作线上代码,提升了在线服务稳定性至99.99%。
特征一致性问题
归因分析:为了提升迭代效率,采用了明文样本的特征保存方式,来达成数据和抽取逻辑解耦,同时引入了不一致的问题,体现在:
分散的特征抽取架构
中心化治理的抽取架构
元数据一致的架构
优化成果:
达成了特征的完全一致性,整个样本拼接率 xx%提升至了94%,多个核心场景的业务指标提升显著。
性能优化
影响性能的关键环节:
归因分析:
解决思路:
在线关键路径优化
样本流动通路优化
解决方案:
优化成果:
5.3 推荐系统的可解释建设-Debug 平台
这里为什么把 debug 平台作为一个独立的模块单独出来讲,在我看来很多公司忽视了推荐可解释性平台建设的重要性,大家过分的依赖于数据本身的表现而忽略了背后的逻辑,从而导致了一个现象:就是往往我们做的每一个实验都是正向的但是累积一段时间下来,整体大盘指标反而没有任何进展。这跟当下的推荐优化过分依赖 ab 实验平台,忽略了可解性建设有直接的关系,很多方向的探索大家都处在“知其然,不知其所以然”的状态。
推荐系统的可解释性困局
可解释性的两层含义:
由于推荐系统的参与者众多,内容、用户量级巨大,架构复杂,因而构建一个可解释的系统面临了极大的挑战。
可解释性困局
新闻 Debug 平台的设计目标
平台全景
架构全景
平台能力
核心链路设计
数据流转架构
5.4 端到端的稳定性建设
新闻的业务特点:时效性强、热点突发多,导致 QPS 波动大,对系统稳定性冲击大。
稳定性治理的措施:
自动容灾的架构设计
原则:制定并且遵循标准、规范和最佳实践,构建防腐层避免新的技术债务的累积。
新闻的架构优化,从21年开始一直持续到现在,系统从不足99%的可用性提升至了99.99%,整体成本下降了60%,取得了一些成果。同时,系统的优化之路又永远都没有终点,因为业务总是在向前的,新的问题不断涌现,我的认知也随着解决问题不断提升,“路漫漫其修远兮,吾将上下而求索”,以此共勉。
-End-
原创作者|董道祥