fc013 发表于 2016-5-29 17:18:46

Spark在微博Feed算法中的应用实践


问题导读:
1.新浪微博的三层架构是怎样的?2.新浪微博的Feed使用场景?3.新浪微博的Feed是怎样排序的?

http://www.aboutyun.com/static/image/hrline/4.gif

一、新浪微博及其三层技术架构
新浪微博是中国领先的社交媒体平台,是一个基于用户关系来分享、传播以及获取中文内容的平台。用户可以通过 Web、移动等各种客户端,以文字、图片、视频等形式更新信息,同时实现即时分享。
根据微博 2016 年第一季度财报数据,截止一季度末,微博月活跃用户达到 2.61 亿,日活跃用户达到 1.2 亿。在微博垂直运营的行业中,已经有 12 个行业的月均阅读量超过 100 亿。微博将与很多专业机构在内容生产,账号成长,收入变现等多个方面展开合作,在不同垂直领域构建行业生态。
巨大的用户规模和业务访问量,需要强大技术系统支撑,下面将介绍微博的技术架构。微博技术架构最基本的设计思想是分层,这是大中型互联网系统的常见设计思路。
微博的技术架构基本上分为三层:业务层、平台层、大数据层。

业务层主要直接面对用户,为用户提供产品功能,满足用户需求。这里的用户包括微博产品大众用户、商业产品企业用户、第三方应用开发者等。微博为大众用户提供了 Web、移动客户端等产品,为企业用户提供了粉丝通等商业产品,为第三方开发者提供开放平台等产品,动态平台、广告服务平台、开发平台等系统分别提供相应的技术支持。
平台层主要提供微博内部公共功能接口以及承载微博业务流量。平台层主要有接口、缓存、存储、队列和队列处理等模块。
接口模块主要实现与 Web 页面、移动客户端的接口交互,定义统一的接口规范,其中 Feed 服务是最核心的接口服务之一。
缓存模块通过统一的分布式缓存和分级缓存服务,提高系统性能,承载绝大多数业务流量,目前微博主要使用 Redis 和 Memcached 等作为缓存。
存储模块主要用于存储业务数据,包括千亿级的微博内容和用户关系数据,目前微博内容主要使用 MySQL、Redis 和 HBase 等存储系统。
队列模块和队列处理模块是异步化的关键。以发布微博为例,发博是一个非常复杂、耗时的操作,它要写入数据库、统计索引、内容分析、传入后台。
如果我们要把所有的步骤都做完,用户需要在前端等待很长的时间;如果某一个环节失败,即使已经成功写入数据库,用户将得到“发布失败”的提示,这样的用户体验非常糟糕。
异步化之后,发布微博成为一个异步操作,发布成功我们就提示成功,同时将微博写入到 MemcacheQ 等消息队列中;队列处理模块在后台循环消费消息队列,进行写入数据库、内容分析等复杂、耗时操作。
异步化能显著减少写操作接口响应时间,减少用户等待时间,改善写操作用户体验;同时,由于复杂操作转化为后台处理,提高了接口并发处理能力,极大提高了整个系统吞吐量。
大数据层主要提供基础的数据服务和算法服务。
存储模块包括存储系统和队列系统。存储系统包括存储离线数据的 HDFS 分布式文件系统、存储在线数据的 Redis 和 HBase 等 NoSQL 系统、以及存储在线数据的关系数据库 MySQL 系统。队列系统包括微博自主研发 Firehose 队列,开源的 Scribe 和 Kafka 队列。队列系统用于实时接收事件和数据。
计算模块包括计算系统和算法系统。计算系统包括处理离线数据的分布式计算系统、处理队列实时数据的实时流计算系统。算法系统包括模型训练机器学习系统,以及实时、离线生成各类特征的特征工程系统。
服务模块包括数据服务和算法服务系统,提供用户画像、标签服务、推荐引擎等数据服务,提供文本处理、图片处理、分类预测等算法服务。
应用模块主要承担数据、算法和产品策略的结合。大部分的基础数据和算法已经基本可用,但是由于产品场景的不同,数据、算法需要和产品策略进行针对性的融合和优化,最大限度提高最终产品效果。
业务层、平台层、大数据层相互依赖,结合在一起形成完整的技术生态系统。
二、微博的 Feed 场景
当你发布一条微博,关注你的粉丝会在一定的时间内收到你的微博。你的粉丝不仅仅会关注你,还会关注其他朋友、明星、网红、企业、政府等。当他在 Web 或者移动客户端进行阅读消费时,若干微博依次展现形成了信息流,我们称之为 Feed。
Feed 的基本流程是:当你发布一篇微博,会将该微博作为物料进行存储;当你的粉丝进行 Feed 阅读消费时,会将他的关注人的微博进行筛选和聚合,并进行组合排序,最终展现到你的粉丝面前。流程如下图所示。

1. 推模式和拉模式
Feed 在技术上,有推模式和拉模式两种实现。
推模式就是,用户 A 关注了用户 B,用户 B 每发布一个微博,后台遍历用户 B 的粉丝,往他的粉丝的 Feed 里面插入一条物料。与推模式相反,拉模式则是,用户每次刷新 Feed 时,都去遍历关注的人,把关注人最新的微博物料拉取回来。由于微博是以单向关注为主的社区,关注和粉丝非常不对等。亿级的粉丝数对推模式的时效性、有效性等方面形成很大挑战,因此,微博采取拉模式为主进行 Feed 的聚合,在某些特殊场景下才使用推模式进行补充。
2. 和 Spark 结合
在算法方面,内容质量模型、排序模型、防抓站模型等都和 Spark MLlib 进行了结合;在物料方面,动态物料生成等方面有使用 Spark Streaming;在特征方面,Spark Streaming 用于生成实时特征,Spark 和 Spark GraphX 等用于生成用户特征、关系特征等离线特征。

3. 遇到的问题
在 Feed 场景下,物料问题是我们遇到的第一个问题,物料方面包括数量和质量的问题。我们通过引入关系物料、非关系物料、个性化兴趣物料来解决数量问题,通过引入用户质量模型、内容质量模型类解决质量问题。排序问题是最重要的问题之一,其中主要是排序优化的问题,我们通过引入样本、模型、特征等来解决,下一节将会进行详细介绍。
三、微博的 Feed 排序场景
Feed 本质是上物料的分发,就是说当用户消费 Feed 时,系统需要把跟用户有关的或者用户感兴趣的事情告诉他。我们在优化 Feed 时,发现了如下问题:

[*]用户体验:用户 Feed 阅读体验很难评估和量化,用户 Feed 阅读体验很难优化;
[*]低质内容:用户 Feed 质量参差不齐,低质内容影响用户体验;例如由于传播的低成本,个别名人大号在过度的使用消息通道,生产大量用户不感兴趣的低质内容;由于利益关系,容易出现广告行为、僵尸行为和作弊行为;
[*]信息过载:用户每天只阅读部分微博,大量优质内容被错过;有很大部分人关注了成百上千的账号,每天有千上万的微博新 Feed 供消费,而实际阅读微博数只有几百几千,很多有价值的内容被沉寂;
[*]个性化:用户千人千面,有个性化需求;虽然每天收到大量信息,即使有不少是热点内容,但是大部分不是自己感兴趣的信息;基于用户关注维度的兴趣阅读效率不高,例如用户关注了一个兴趣领域的同行,但这个同行却大部分时候在晒娃。

我们的解决思路和方案是:

[*]引入互动,通过样本来量化用户体验;
[*]引入排序模型,优化排序和用户体验;
[*]加入用户和微博质量特征,控制低质内容,扶持优质内容;
[*]加入用户个性化特征,挖掘个性化需求。

排序的三大要素:样本、模型、特征。样本和特征结合到一起进行离线训练,得到排序模型;模型和特征结合到一起进行在线预测,最终用于 Feed 的排序。

1. 样本
我们通过引入样本来量化用户体验。
用户阅读 Feed 中的微博内容,我们称之为曝光;微博在 Feed 中展示时,有若干区域可以供用户进行点击和互动,如下图中的红色区域。互动包括转发、评论、赞等强互动,阅读、点击正文页、点击作者、点击长文、点击图片等弱互动,以及“不感兴趣”等负反馈互动。

通过是否互动来定义正负样本,在曝光一定时间内接收到相应互动,我们称之为正样本,否则为负样本。
定义正负样本之后,我们需要进行样本数据的收集,包括实时样本收集和离线样本收集。

[*]当微博在 Feed 流曝光时,会将曝光相关数据写入 Scribe 和 Kafka 等消息通道;
[*]有用户对微博进行互动时,互动数据会写入 Firehose 等消息队列;

Spark Streaming 和 Storm 等实时流处理系统会实时获取曝光和互动数据,并联合形成相应的正负样本,在线的正负样本同时会实时地同步到离线 Hadoop 系统中。系统流程如下图所示。

2. 模型
我们通过引入排序模型来优化排序,主要工作有模型训练和模型预测。
在模型训练方面,由于我们每天有千亿级的曝光,样本数据多,特征维度多;因此我们采用工业上通用的逻辑回归模型(Logistic Regression,LR),并使用 Spark MLlib 进行离线训练。
逻辑回归模型足够简单,速度较快,但是学习能力有限;我们引入 GBDT(Gradient Boosting Decision Tree)和逻辑回归模型进行融合。
在模型预测方面,为了和线上系统整合,我们开发了模型 RPC 服务(ModelService),如下图所示。
为了保证服务的高可用性和高可扩展性,我们将模型服务设计成无状态的完整独立服务。经过负载均衡模型进行模型服务的健康状态监测,如果某个模型服务出现问题,将被摘除,不再对外提供服务。同时,负载均衡模型还提供流量分发功能。由于每个模型服务都是完整和独立的,我们进行系统扩展和服务扩容非常方便。

总结下模型方面的流程,样本通过 Spark MLlib 进行离线训练;经过评估,将稳定的模型通过到线上的模型服务(ModelService)中;模型服务(ModelService)和在线特征结合起来,对 Feed 排序进行在线预测。系统流程如下图所示。

3. 特征
我们引入特征来区分微博质量和用户个性化需求。

[*]从属性上,可以分为微博特征、用户特征等特征;
[*]从实现上,可以分为离线特征和实时特征。

我们引入 Hadoop 和 Spark 等分布式系统来解决离线特征的解决数据量问题和计算量问题,通过引入 Hive/Spark SQL 解决离线特征的开发效率问题。我们引入 Storm 和 Spark Streaming 等实时流计算系统进行实时计算,开发流式语言 WeiPig 解决开发效率问题。内部开发的流式语言 WeiPig 提供了Pig on Storm 和 Pig on Spark Streaming 的功能。语法和 Pig 语法很类似,提供了若干原语,包括定义流式拓扑结构的 topology,定义数据输入的 input,定义数据处理的 task,定义数据输出的 output。同时还支持自定义 udf 函数等功能。语法示意如图所示。

WeiPig 基本解析流程是通过语法解析,形成语法抽象树;通过遍历 AST,生成执行逻辑;通过反射生成可以在 Storm 或 Spark Streaming 中可执行的原语和代码。通过将生成的 Storm 和 Spark Streaming 作业提交到集群中进行真正的实时流处理。
在 Storm 和 Spark Streaming 选项方面。Storm 使用流水式并行计算方式,数据流入到计算节点进行计算,移动数据而不是移动计算;Spark Streaming 使用数据批处理方式,切分数据形成任务进行计算,移动计算而不移动数据。Storm基本是若干毫秒的延迟,Spark Streaming 一般是若干秒的延迟。对于要求毫秒级延迟或者处理过程相对简单的应用,我们一般选用 Storm;对于秒级或分钟级延迟或者处理过程包含聚合等复杂运算的应用,我们一般选用 Spark Streaming。
总结下特征方面的流程:

[*]当用户发布微博时,发博数据会写入 Firehose 等消息队列;
[*]微博在 Feed 流曝光时,会将曝光相关数据写入 Scribe 和 Kafka 等消息通道;
[*]有用户对微博进行互动时,互动数据会写入 Firehose 等消息队列。

Spark Streaming 和 Storm 等实时流处理系统会实时获取发博、曝光和互动数据,抽取相应的特征,形成实时特征。实时特征同步到离线 Hadoop 系统之后,经过 Spark、Hive、Hadoop 等分布式计算,生成新的离线特征。离线特征定期加载到在线特征库中,和实时特征进行融合,最终形成统一的在线特征库。系统流程如下图所示。

四、总结
样本、模型、特征等是 Feed 排序三要素,样本用于量化用户体验,模型用于优化排序和用户体验,特征用于区分微博质量和用户个性化需求。样本和特征结合到一起进行离线训练,得到排序模型;模型和特征结合到一起进行在线预测,最终用于 Feed 的排序。样本、模型、特征等整合起来的系统流程如下图所示。


xuliang123789 发表于 2016-5-29 22:10:07

谢谢楼主,学习 一下,赞~~

lingyufeng 发表于 2016-5-30 08:46:03

谢谢分享
页: [1]
查看完整版本: Spark在微博Feed算法中的应用实践