vivo 应用商店推荐系统探索与实践

标签: vivo 应用商店 推荐系统 | 发表时间:2021-03-22 02:18 | 作者:vivo互联网技术
出处:https://juejin.cn/backend

介绍 vivo 应用商店推荐系统如何高效支撑个性化的推荐需求。

一、前言

商店的应用数据主要来源于运营排期、CPD、游戏、算法等渠道,成立推荐项目之后也没有变化,发生变化的是由推荐系统负责和数据源进行对接,商店服务端只需要和应用推荐系统进行对接即可。

如果读者以为我们单纯是把商店服务端代码给照搬到推荐系统这边来了那就真的是too young too simple 了,不做优化或者升级直接copy一个系统是不可能的,这辈子都不可能。以下我将介绍我们如何去设计和规划应用推荐系统的。

二、面临的挑战

在笔者眼中,商店应用推荐系统除了要具备高性能、高可用性及核心指标的监控能力之外,还有一个核心的能力就是高效支撑商店流量场景接入个性化推荐。

如何定义高效支撑?

  • 最起码能支撑三四个并行的需求同时进行吧。
  • 一个需求开发周期最起码不能超过2天吧。
  • bug少一点吧,平均下来每个场景不应该超过2个吧。
  • 产品同学的常态性的需求基本都能快速支持吧。

分享我们一个应用推荐的策划case看看:

在xx场景下,

如果主应用A属于应用类,

  • 则首先从从x1数据源去取Q1队列。
  • 然后从x2数据源去取Q2队列。
  • 然后用Q2队列去截断Q1队列,交集之后进行同开发者过滤和一级分类过滤。
  • 如果交集为空则用Q2去兜底,然后取交集队列的n1和n2 位置上的元素作为返回队列。
  • 如果前面都没有取到数据的话从大数据xxx表中按照主应用下应用点击的概率取点击率最高的分类下的n个,同时需要对这些数据进行队列内的同开发者过滤。

如果主应用A属于游戏类,

  • 则xxxx
  • 进行二级分类过滤
  • 如果量不足的话,则从x(n)取数据然后进行处理,
  • 如果数据不足3个的话,需要从周榜单中取同一级分类下的应用按照下载排行进行兜底。

没错,读者朋友不要怀疑自己,为了不把各位读者大大绕晕,我们这里只是挑选了一个简单的需求。实现这么一个功能也没有什么大不了的,但是当这种个性化推荐需求有几十个,后面还可能一致扩展下去的时候会不会心里发慌?来,简单看下我们现在个性化推荐的一部分需求,如图(一)所示:

图(一)

使用商店服务端之前的case by case的开发方案,无论如何都无法实现上文中描述的要支撑商店高效接入推荐场景了,接着就是我们如何去实现优化的过程了。

三、如何解决

为了更好的说明解决思路,我们从实际思考过程出发,一步步讲解问题的解决过程。

3.1 业务流程抽象

单纯从策划上面来说,我们每个场景都需要至少做如图(二)中的几件事情:

图(二)

  • **获取推荐列表:**调用各个数据源获取的推荐队列(需要注意的是不同场景下调用的接口并不一致,此外接口返回的字段和结构可能也不一样)。
  • **队列融合:**将1中提到的进行交集或者并集并等操作。
  • **数据过滤(队列内/队列间):**在队列中进行各项过滤,过滤操作主要是为了提升相关性。
  • **数据兜底:**指在队列数据不够的时候,用榜单兜底,可能取周榜单数据的同一级分类数据,同二级分类数据。

笔者从开发便捷性出发,对模型进行了进一步的调整,调整后为图(三)

图(三)

获取队列后对队列进行安装过滤和队列内过滤(如主应用同开发者过滤等)可以进行流程合并,主要有如下的原因

  • 方便定义每一个数据源的过滤策略,实际需求中不同的队列也会使用不同的过滤策略。
  • 这种方式非常匹配模板设计模式,能确保我们获取推荐列表过程是一致和稳定的。

3.2 抽象流程延伸

到图(三)这里,读者会发现我们依然没有能够解决我们前面提到的各种推荐场景里面的差异化过程。

其实在接触几个需求以后,我们会发现,想要在一套代码里面去解决这么大的差异性,几乎不可能,或者即使实现了,那么也会让代码变得无比复杂。与其这样子,我们还不如正视这种差异性,让差异在场景插件里面去实现,我们花更多的精力去打理主干。

那么为了支持让场景能够具备灵活的扩展能力,笔者在基于图(三)的基础上增加了四个环节:

  • **队列结果线程内共享:**使用ThreadLocal来实现。存储各推荐队列的结果主要是为了便于后续使用某推荐队列做填充的需求,另外就是避免需要再重复请求三方数据接口,减少接口重复调用。
  • **插件队列兜底:**主要目的是在过滤后在数量不足需求的情况下,使用指定的队列完成填充,场景插件亦可按需填写实现填充逻辑,实现队列内容的补充。
  • **插件接口回调:**该环节主要是对前面的队列做个性化的处理,如对队列进行干预等,没有将插件接口回调和插件队列兜底融合在一起主要原因是插件队列融合可以实现可配置化的设置。
  • **周榜单兜底:**提供通用的周榜单数据查询能力,支持按照各种维度进行查询,此部分数据作为队列的最后兜底。

拓展后的流程图如图(四)所示

图(四)

3.3 整体逻辑框图

经过上述的分析可知,我们可以尽可能的把个性化的场景内容放在插件层实现,框架层负责加载按场景加载场景插件的具体个性化推荐逻辑。

系统从分层思路上讲从上至下共分为:插件层,框架层,协议适配层,数据源服务层,原子服务层,基础服务层,上层通过 SDK 依赖下层的服务(接口),各层次职责为:

  • **插件层:**各个场景对应的插件,框架层对插件回调或者扩展接口提供默认实现,插件层按需实现具体的逻辑。
  • **框架层:**定义推荐数据的核心流程和执行逻辑,回调插件层的实现的扩展和回调接口。
  • **协议适配层:**负责按照场景找到场景对应的数据源服务,并封装转换协议和进行数据转换。
  • **数据源服务层:**与各个队列提供方提供的RPC服务封装层。
  • **原子服务层:**过滤类型的相关服务,主要是依赖于商店的 RPC 服务,使用组合的设计模式,服务可以进行组合。
  • **基础服务层:**支持从开发者、一级分类、二级分类、应用类型等纬度进行相关性的判断或者过滤,同原子服务层一样,此层服务也是原子粒度,支持进行组合控制。

至此,相信大家都知晓了,针对于个性化的推荐,我们的开发工作最终将聚焦于开发场景插件,不需要再额外开发每一个业务流程了。

应用推荐系统架构

3.4 关键实现

在完成第三步整体逻辑框图设计之后,我们从场景参数定义,服务设计原则,设计模式使用,场景热插拔等方面进行了相关的方案研究并最终实现了方案的落地。

3.4.1 场景服务参数定义

为实现推荐场景足够通用,我们将数据源层,原子服务层,基础服务层的内容进行了服务配置的映射,通过在配置中定义对应的配置项来实现服务的映射和组合,针对于差异性的内容在插件层进行实现。以如下的配置项示意图来说明:

  • **sourceMap:**场景服务定义为map用于支持场景下多个模块或者实验组的情形,其中key为模块ID,商店服务端请求推荐的时候,需要携带此参数。
  • **cpdRequest 、algorithmRequest 、gameRequest:**用于定义对应的RPC调用的请求参数。
  • **filterRequest:**用于定义队列内的过滤请求,如主应用同开发者过滤等。
  • **unionStrategy:**定义队列合并和融合及队列间的合并规则。
  • **supplement:**兜底策略;
  • **sourceList:**使用的数据源,如上图中定义了两个数据源,则表示在此场景下需要从两个数据源获取数据,然后进行队列合并及后处理。

3.4.2 服务原子化与唯一化

实现服务原子化与服务唯一化对本系统至关重要,在实现过程中是严格遵照如下两点来:

应用推荐依赖的三方RPC服务及内部的一些过滤逻辑都封装成了细粒度的原子服务(方法)的SDK。SDK中的内容不包含个性化推荐场景的具体业务性的能力,体现的重点是基础功能项,业务内容需要在场景插件中进行实现,统一类型的服务尽可能支持组合。

服务唯一化在对于实现系统的收敛和代码规模可控至关重要,我们也是不断的在朝着这个努力。各服务层都是以SDK的形式对外提供相关的功能,在SDK中实现服务调用入口的唯一性。

3.4.3 合理使用设计模式

系统中使用了较多的设计模式来优化整体架构,如下重点来介绍使用的模板设计模式、策略模式及组合模式:

在获取推荐原始队列中使用了模板设计模式和策略模式来实现此过程。

使用模板设计模式的好处显而易见,能够容易促进此部分处理逻辑流程化。

针对不同的数据源,需要使用不同的数据源服务和方法,使用策略模式的好处是便于定义在不同场景下对不同的接口的调用。

同类型的原子服务或者方法尽可能支持组合模式,这种会为后续的扩展提供很大的便利性。

以实际的实现方法来说明,在我们定义过滤类型的时候,支持传入多个过滤类型,上层业务在使用的时候按需传入即可。使用组合的设计模式在提升扩展性方面起到了巨大的作用。

3.4.4 场景的热插拔

系统中为实现场景之间的隔离和互不干扰,笔者使用了Java SPI的方式,在框架层定义了场景接口,接口实现类则在各个场景在独自的Jar中实现。这种方式有助于插件程序对框架层和基础服务层的侵入性降到最低。

四、带来的改变

以前商店服务端在各个接口的service层写完整的推荐队列获取、融合、组装、过滤逻辑,有大量的重复内容,且随着版本的不断迭代,有很多版本不同的处理逻辑夹杂在一起,导致改造难升级难,牵一发动全身。目前应用推荐系统在两个方向带来较大改善:

  1. 流程框架的逻辑完全抽象并独立,各个业务场景只需要按需写很少的插件回调逻辑即可,(不涉及十分特殊的场景可完全不用写插件回调扩展,通过配置对应的场景规则配置即可,可完全实现免开发,目前有30%左右的场景免开发)。
  2. 场景之间完全隔离和独立, 涉及复杂的功能升级可通过升级对应的场景id或者模块id来做增量实现,不影响现有逻辑。

五、写在最后

通过上述相关的方案落地,针对于各个推荐场景,我们大概减少了75%的开发工作量,同时bug率也得到大幅度的降低。

作者:vivo-Huang Xiaoqun

相关 [vivo 应用商店 推荐系统] 推荐:

vivo 应用商店推荐系统探索与实践

- - 掘金 后端
介绍 vivo 应用商店推荐系统如何高效支撑个性化的推荐需求. 商店的应用数据主要来源于运营排期、CPD、游戏、算法等渠道,成立推荐项目之后也没有变化,发生变化的是由推荐系统负责和数据源进行对接,商店服务端只需要和应用推荐系统进行对接即可. 如果读者以为我们单纯是把商店服务端代码给照搬到推荐系统这边来了那就真的是too young too simple 了,不做优化或者升级直接copy一个系统是不可能的,这辈子都不可能.

Min-Hash和推荐系统

- - xlvector - Recommender System
前几年看Google News Recommendation的那篇Paper,对里面提到的MinHash的算法基本没有注意,因为之前的习惯都是只注意论文的模型那块,至于怎么优化模型一般都只是扫一眼. 不过最近看了大量的Google Paper,发现Google在实现一个算法方面确实有很多独到之处. 其实,Min-Hash是LSH(Locality Sensitive Hash)的一种,我之前对LSH的了解仅仅限于知道它能把两个相似的东西Hash成两个汉明距离接近的2进制数.

推荐系统实战

- - 博客园_首页
推荐算法:基于特征的推荐算法. 推荐算法准确度度量公式:. 其中,R(u)表示对用户推荐的N个物品,T(u)表示用户u在测试集上喜欢的物品集合. 集合相似度度量公式(N维向量的距离度量公式):. 其中,N(u)表示用户u有过正反馈的物品集合. 其中,S(u,k)表示和用户u兴趣最接近的K个用户集合;N(i)表示对物品i有过正反馈的用户集合;w(u,v)表示用户u和用户v的兴趣相似度;r(v,i)表示用户v对物品i的兴趣.

推荐系统杂谈

- - 后端技术杂谈 | 飒然Hang
推荐系统是近些年非常火的技术,不管是电商类软件还是新闻类app,都号称有精准的推荐系统能给你推送你最感兴趣的内容. 现象级的资讯类app“今日头条”就得益于此成为了势头非常猛的一款产品. 本文就针对推荐系统讲述一些相关概念和实践经验. 首先需要明确的就是推荐系统的目标,一般来说不外乎以下几个:. 用户满意性:首当其冲的,推荐系统主要就是为了满足用户的需求,因此准确率是评判一个推荐系统好坏的最关键指标.

步步高 vivo 智能机更多功能界面公布

- Johnny - Engadget 中国版
此文章网址 | 转寄此文章 | 回应.

步步高 vivo 智能机 V1 首张定妆照公布

- starry heavens - Engadget 中国版
终于看到真容了,步步高的智能手机 V1 定妆照亮相,这款机子以女性为主打对象,一些界面设计我们已经提前看到,可惜这次官方图依然没有公布具体的规格配置,从效果图可以看到后置了 500 万像素摄像头,带 LED 补光灯,后底部是一个 SRS 音效标识. 而第一款新品 V1 的工程机将在今天(9 月 26 日) 2011 北京国际通信展上亮相.

vivo AI 计算平台的K8s填坑指南

- - InfoQ - 促进软件开发领域知识与创新的传播
在2018年底,vivo AI 研究院为了解决统一的高性能训练环境、大规模的分布式训练、计算资源的高效利用调度等痛点,着手建设AI计算平台. 白驹过隙,将近两年时间过去了,平台的建设和落地取得了很大的进展,成为了vivo AI领域的核心基础平台. 平台现在已经有超过500多个用户,来自人工智能、影像、互联网等多个部门.

事件驱动架构在 vivo 内容平台的实践

- - 掘金 架构
当下,随着微服务的兴起,容器化技术的发展,以及云原生、serverless 概念的普及,事件驱动再次引起业界的广泛关注. 所谓事件驱动的架构,也就是使用事件来实现跨多个服务的业务逻辑. 事件驱动架构是一种设计应用的软件架构和模型,可以最大程度减少耦合度,很好地扩展与适配不同类型的服务组件. 在这一架构里,当有重要事件发生时,比如更新业务数据,某个服务会发布事件,其它服务则订阅这些事件;当某一服务接收到事件就可以执行自己的业务流程,更新业务数据,同时发布新的事件触发下一步.

vivo数据库与存储平台的建设和探索

- - 掘金 架构
本文根据Xiao Bo老师在“ 2021 vivo开发者大会"现场演讲内容整理而成. 公众号回复**【2021VDC】**获取互联网技术分会场议题相关资料. 一、数据库与存储平台建设背景. 以史为鉴,可以知兴替,做技术亦是如此,在介绍平台之前,我们首先来一起回顾下vivo互联网业务近几年的发展历程.

vivo 短视频推荐去重服务的设计实践

- - 掘金 架构
vivo短视频在视频推荐时需要对用户已经看过的视频进行过滤去重,避免给用户重复推荐同一个视频影响体验. 在一次推荐请求处理流程中,会基于用户兴趣进行视频召回,大约召回2000~10000条不等的视频,然后进行视频去重,过滤用户已经看过的视频,仅保留用户未观看过的视频进行排序,选取得分高的视频下发给用户.