0到1再到100 蘑菇街搜索与推荐架构的探索之路

丁小明,花名小宝,蘑菇街搜索技术团队负责人。2011年底加入蘑菇街,2013年开始负责搜索团队,见证了蘑菇街一路蓬勃发展的历程,也和团队一起从零起步摸爬滚打,打造了蘑菇街的搜索推荐体系,包括自主研发的C++主搜引擎和广告引擎、实时个性化推荐系统、基于开源Solr/ES深度定制的实时搜索平台等。

小宝·蘑菇街搜索技术团队负责人

以下内容根据小宝老师在WOTA2017 “电商大促背后的技术挑战”专场的演讲内容整理。

我将和大家分享蘑菇街在搜索推荐上踩过的坑及在探索路上的经验总结。我们的经验虽算不上业界最佳实践,但也是一步步从0到1再到100,希望大家可以从中得到一些收获。

搜索架构的探索之当前现状

蘑菇街搜索当前架构

如上图,是蘑菇街当前搜索架构,分为在线和离线两部分。在线部分主要职责是处理在线的搜索请求。离线部分的主要职责是处理数据流。

在线请求链路

如上图,是整个在线请求链路,主要分为topn->qr->引擎->精排->透出五个环节。

第一步,请求首先进入topn系统,做ab配置/业务请求链路配置。

第二步,请求进入QR改写系统做切词,同义词扩展,类目相关性,插件化等。

第三步,进入UPS用户个性化数据存储系统。

第四步,投放层得到UPS和QR两部分的数据后,放入搜索引擎做召回。搜索主要会经过一轮海选,海选的依据是文本相关性和商品质量,这样做是为确保召回的商品质量大致可靠。之后会经过多轮初选,过程中会应用到更复杂的算法模型,对海选的结果进行排序。搜索引擎得到粗排的结果约千级别。

第五步,粗排结果进入到精排系统,精排系统主要通过算法,做个性化排序、实时预测,精排和引擎类似,也支持多轮排序。经过精排系统之后,最终把结果透出给业务层。

蘑菇街统一引擎系统

如上图,左侧红色框内是蘑菇街统一引擎系统,包含用户个性化存储系统、精排存储、商品引擎、广告引擎等。由于这样的形式维护成本特别高,故做了右图这个统一的Zindex内核架构。这个架构的最底层是共享内存分配器,再上层是可支持不同数据结构的各种引擎,再上层是索引管理。基于这个架构,不同的引擎可根据各自需求去创建自己的索引。

跟这个架构相关的,就是我们的运维平台,是基于公司Docker虚拟化技术做的一个运维平台,能够非常快的支持索引创建,包括创建之后整个索引数据的管理。还有就是排序平台,用来提供算法配置变更服务。

搜索架构离线部分的数据流程

如上图,是离线的数据流程的情况,主要职责是数据流的处理,完整的索引数据分为算法数据和业务数据。

算法数据参与排序,整个链路从最前端ACM打点、再落到整个数据仓库、经过清洗之后,在数据平台上跑训练脚本,得出的特征导到特征平台,再同步到线上。

业务数据的主要来源就是DB,DB中主要存储商品、店铺之间的数据,业务变更主要基于mysql bin-log事件监听,变更之后做全量和增量。全量每天定时索引操作、增量会流到MQ,再通过业务拼装推到线上。

搜索架构的探索之演变历程

蘑菇街搜索架构主要经历导购时期(~2013.11)、电商初期(2013.11~2014.11)、Solr主搜(2015.4~2016.3)、C++主搜(2015.8~2016.11)、平台化(2017.1~now)五大阶段。

蘑菇街搜索架构现状简化版

为了更清晰直观进行对比,我把当前搜索架构简化成如上图所示的业务、投放、排序、召回、数据流五大层。接下来我们来看看,我们从最早期,都经历哪些演变,一步步走到现在。

蘑菇街搜索架构导购时期架构

如上图,是~2013.11导购时期的架构,有用到放在PHP代码里的业务+投放、用Java搜索引擎Solr做的召回+排序和数据流三层。这个时期,排序需求不是很迫切,更多侧重的是商品整体的丰富度和新颖度。简单理解,热销排序等于喜欢乘10加上收藏乘50,基于Solr的改造来实现。

在电商转型初期(2013.11~2014.11),由于卖自己的商品,流量变得更值钱了,工程师会想法设法去提升流量的效率。同时用户行为也在增加,产生更多的数据。还有增量管理复杂,数据量大、Optimaize风险大、导购、广告和搭配等多类型商品透出等等。其中最明显挑战就是排序特征变多、数据变大、次数频繁。

蘑菇街搜索架构转型初期架构

面对这些挑战,当时的思路是把算法独立成单独Java工程做算分,但百万商品百种排序,算法排序达G级别,这些排序数据需要作用于搜索引擎,快速生效,问题是用增量的方式会引来索引碎片的增加,会给线上引擎稳定性带来波动。故另辟蹊径,用在Solr进程中设置堆外内存来管理这部分排序数据。

总结来说,转型初期整体的解决方案就是把算法独立出来单独去做,把部分分数尽快同步到引擎,进行生效。这样的方法,当时线上效果很显著,但随时间推移又有新问题出来:

  1. 规则排毒->LTR,算法排序需求多;
  2. 排序灵活性制约:计算好的分数离线推送到Solr;
  3. Solr内存压力:GC/段合并;
  4. 静态分,相关性差;
  5. 大促相关性问题:搜索“雨伞”,雨伞图案的连衣裙会排在前面;

Solr主搜整体架构

针对这些新问题,(2015.4)Solr主搜改造,支持Rank插件(Ranker->Scorer),配置化+动态化,整体架构如上图。应对相关性问题,新增QR系统、应对内存压力,做Solr升级(Docvalues),算法分走动态字段增量,同时投放方式也渐渐形成Topn系统,对外对接不同的搜索场景。

Solr架构解决相关性、算法变更线上排序等问题,但新问题在于虽用机器学习的排序做法,但那个时期主要是爆款模型,有很多个性化需求模型同时对不同人要有不同的排序结果,还有一些重排序或打散等更加复杂的需求。因Solr实现机制的限制,只能做一轮排序,想要改动比较难。另外,Solr整个索引结构非常复杂,二次开发成本高,内存、性能上也慢慢地暴露出很多问题,同时还有Java的GC也是不可逾越的鸿沟。

当时多轮排序的需求,除了做一些文本相关性,还相对商品做品牌加权,如想扶持某些品牌、做类目打散等,这些在单轮排序内做不到,原来的方式只能把多轮融合在一个排序中搞定,但效果会很差。

C++主搜架构

如上图,是C++主搜架构(2015.8~2016.11)上线,在整个性能和排序方面做了定制,可支持多轮排序、整个内存采用内存方式,由排序体系支撑。这个阶段整体来看,相对是完善的,每层,整个系统都成型,可数据流环节又出现了三个问题:

  1. 全量无调度,都要依靠流程制约
  2. 增量带来算法分数不可比,会带来一些线上排序的抖动
  3. 业务数据增量对服务接口压力过大(促销故障)

全量的整个链路

如上图,是全量的整个链路,算法序列的整个链路靠时间约定,数据容灾机制弱。所以大促时,前置任务延迟全量做不了,线上内存几乎撑爆,经常性全量延时,必须手动去处理。还有算法误导排序分,导致线上错乱,增量恢复时间长。

要解决这个问题,我们首要引入一个基于Zookeeper的调度系统,把整个数据流驱动起来同时支持错误报警。容灾部分的思路就是增加排序SOS字段、基于HBase定期生成全量快照,快速回档、单算法字段修复等。

两次算法增量分数不可比,增量生效特别慢。如时刻1算出商品是90分,时刻2是60分,就会引起线上排序抖动,主要因算法两次序列导致整个数据分布不同,特别到大促时期,不同时段成交数据变化特别快,商品排序的波动非常明显,增量数据同一批正常,但两次见就会出错。当0点大家在疯狂购物的时候,变更非常频繁,会导致排序错乱。算法数据出错后,生效时间也会比较慢。

如上图,我们的解决方案是通过小全量的方式把算法、分数单独拖到线上引擎本地,在引擎本地依次一次加载,直接切换的方式,让每一次算法增量数据的数据加速生效,容灾也会加快。

如上图,由于变更都是Doc级更新,每一个字段更新都会调用所有的接口去拼装成一条完整的数据去更新,这导致业务增量压力特别大。大促期间,增量QPS可以达到几千~上万,对下游40多个接口的压力非常大。

如上图,这个问题解决的思路是让引擎,包括数据流支持字段更新。只拼装变更字段、不需要拼装完整的数据,这需要引擎本身支持才能做到。当时上线,收益非常明显,关键接口QPS减少80%以上。

平台化(2017.1~now)是现在正在做的事情。面对UPS、广告、商品多套引擎系统与广告、搜索多套投放系统分别从不同团队合并过来,  维护成本问题。排序计算需求变得更加复杂,尝试用非线性模型等方面挑战,就有了现在整理的架构,思路就是平台化、统一化,把重复的系统整合、数据流做统一。

搜索架构的探索之经验总结

这一路走来,整个搜索架构的探索经验就是在发展前期要简单快速支持线上业务,之后在逐步演变,来满足算法的需求,最后在考虑整个利用平台化、统一化的思路去提升效率,降低成本。

不同阶段要有不同的选择,我们最早基于Solr改写,待团队、人员,包括技术储备上也有实力后,直接重写搜索引擎,覆盖算法的离线、在线链路,做体系化建设。

我们的后续规划是新架构整体平台化继续深入,算法方面加强学习,如深度学习、在线学习等。如深度学习框架的研究和使用,以及图搜工程体系的建设。

推荐架构的探索之发展概述

蘑菇街的推荐架构已经覆盖大部分的用户行为路径,从使用进入APP,到下单成交完成都会有推荐场景出现。推荐架构的整个发展分为发展早期(2103.11~2015.6)、1.0时期:从0到1(2015.6~2016.3)、2.0:投放+个性化(2016.3~2016.12)、3.0:平台化(2016.2~now)四大阶段。

发展早期(2103.11~2015.6)推荐的场景并不多,需求也比较简单,数据离线更新到Redis就好,当时明显的问题是没有专门的推荐系统来承载推荐场景、效果跟踪差、场景对接、数据导入等效率低等。

1.0时期的推荐架构

1.0时期:从0到1(2015.6~2016.3)把推荐系统搭建起来,包含Service层对接场景、推荐实时预测、自写的K-V的系统用来存储推荐结果。这里踩的一个坑是,把实时预测做到离线部分,但其实实时预测更多的是在线流程。

随着时间推移,场景类型(猜你喜欢、搜相似、店铺内)、相似场景(首页、购物车、详情页…)不断增加,算法方面需要实时排序,应对实时的点击、加购等,还有一些个性化排序需求,如店铺、类目、离线偏好等。1.0阶段主要面临三大问题:

  1. 多类型多场景:上线系统不一,缺少统一对接层,成本高;
  2. 场景配置化:场景算法一对一,重复代码拷贝,维护难;
  3. 个性化+实时:缺系统支持;

2.0时期的推荐架构

如上图,2.0时期的推荐架构(2016.3~2016.12)主要解决1.0的三大问题,增加投放层Prism,统一对外对接不同的业务场景,对Prism做动态配置和规则模板。个性化实时方面增加UPS与精排系统。

 2.0时期推荐架构投放层配置化

如上图,2.0时期推荐架构投放层配置化思路是把不变的部分模板化,可变的部分配置化。系统提供召回组建、数据补全、格式化等模板。当时效果很明显,321大促运营位置个性化效果提升20%+,双11大促,会场楼层个性化提升100%+。

大促带来的巨大收益,给整个系统带来很正面的影响,后续推荐架构又面临更多的需求与挑战:

  1. 日益增长的资源位、直播、图像等场景和类型;
  2. 跟美的融合,跨团队跨地域的挑战;
  3. 工程算法用一套代码,整个策略的开发调试都非常复杂,包括工程部分的职责不清问题;
  4. 由于原来模板化的配置,导致一些简单场景复杂化。

针对这些问题,我们需要做的事情就是通用化、平台化。针对整套系统进行统一推荐方案,自动化整体算法对接核心业务流程、以及和算法人员的职责划分清晰,提升双方的工作效率。

3.0时期推荐架构

3.0时期推荐架构 (2016.2~now)与搜索架构类似,系统间职能更加明晰,统一和平台化,主要还是投放层做了改造。

3.0时期推荐架构投放层细节

如上图,  3.0时期推荐架构投放层重要的概念就是场景化,场景应对推荐业务,不同场景会对应不同的策略实现。

推荐架构的探索之总结

推荐架构前期,也和搜索架构一样,需要快速支持推荐业务,不需要花费大量精力去搭建非常复杂的系统。满足业务、算法等需求后,才是平台化提升算法、工程双方的效率。后续平台化继续深入,如针对算法策略的评测和压测工具方面,全场景智能监控报警&容灾。算法支持方面,就是OnlineLearning&强化学习,根据算法效果来设计新产品。

以上内容根据丁小明  老师在“电商大促背后的技术挑战”的演讲内容整理。如有投稿、寻求报道意向技术人请联络 [email protected]

时间: 2024-10-26 04:44:57

0到1再到100 蘑菇街搜索与推荐架构的探索之路的相关文章

lucene.net 3.0.3、结合盘古分词进行搜索的小例子(转)

lucene.net 3.0.3.结合盘古分词进行搜索的小例子(分页功能) 添加:2013-12-25 更新:2013-12-26 新增分页功能. 更新:2013-12-27 新增按分类查询功能,调整索引行新增记录的图片字段. //封装类 [csharp] view plaincopyprint? using System; using System.Collections.Generic; using System.Linq; using System.Web; using Lucene.Ne

OpenglES2.0 for Android:再谈纹理映射

OpenglES2.0 for Android:再谈纹理映射 前言 上一节我们实现了一个简单的纹理映射的例子--一个简单的贴图,这节我们来做一些稍微复杂一点的例子,最后再给我们前面的立方体做一个纹理. 纹理拉伸 重复拉伸方式 这种是经常使用的一张纹理拉伸方式,常用于绘制一些重复的元素,比如我们在游戏绘制一幅方格式的地图时.使用重复拉伸方式使得纹理能够根据目标平 面的大小自动重复,这样既不会失去纹理图的效果,也可以节省内存.如下图所示: 实现起来很简单,我们回到上节的项目,找到我们纹理的工具类Te

一个推荐系统,实现完整的设计-在百度搜索关键词推荐案例

在之前一篇博文中, 有同学在评论中问了个问题: 怎样解决因式分解带来的推荐冷门.热门关键词的问题. 在回答这个问题的时候, 想到了近几年在做搜索推荐系统的过程中, 学术界和工业界的一些差别. 正好近期正在做技术规划, 于是写偏文章说下工业界完整推荐系统的设计.结论是: 没有某种算法可以全然解决这个问题, 多重算法+交互设计, 才干解决特定场景的需求. 下文也对之前的一些博文进行梳理.构成一个完整工业界推荐系统所具有的方方面面(主要以百度关键词搜索推荐系统为例) 完整的推荐系统肯定不会仅仅用一种推

有赞搜索系统的架构演进

摘要:有赞搜索平台是一个面向公司内部各项搜索应用以及部分 NoSQL 存储应用的 PaaS 产品,帮助应用合理高效的支持检索和多维过滤功能,有赞搜索平台目前支持了大大小小一百多个检索业务,服务于近百亿数据. 在为传统的搜索应用提供高级检索和大数据交互能力的同时,有赞搜索平台还需要为其他比如商品管理.订单检索.粉丝筛选等海量数据过滤提供支持,从工程的角度看,如何扩展平台以支持多样的检索需求是一个巨大的挑战. Elasticsearch Elasticsearch 是一个高可用分布式搜索引擎,一方面

深度学习在搜索和推荐领域的应用

/* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/ author: 张俊林 深度学习在搜索和推荐领域的应用 大纲: ?深度学习在搜索领域的应用 –通用框架与抽象模型 –几种常见的DL搜索模型 –搜索周边功能 ?深度学习在推荐领域的应用 扫一扫关注微信号:"布洛卡区" ,深度学习在自然语言处理等智能应用的技术研讨与科普公众号.

Android系统从驱动到上层服务再到应用的两种服务架构方式

Android系统从驱动到上层服务再到应用的两种服务架构方式 1)使用类似sensor service的方式: 此方式用于,service的接口不想暴露给上层activity直接使用的情形例如sensor架构c/s结构,适合多个应用与单个服务通信,binder通信时,做connection的区分即可区分不同的client. 2)使用AIDL直接暴露接口的方式: 这个更适合单个应用与服务通信,多个应用与服务通信时,需要处理接口的重入问题.利用Binder实现的标准JNI,不用你去专门实现自己的JN

lucene.net 3.0.3、结合盘古分词进行搜索的小例子(分页功能)

转自:http://blog.csdn.net/pukuimin1226/article/details/17558247 添加:2013-12-25 更新:2013-12-26 新增分页功能. 更新:2013-12-27 新增按分类查询功能,调整索引行新增记录的图片字段. 最新盘古分词dll和词典管理工具下载:http://pangusegment.codeplex.com/ 词典下载:http://pangusegment.codeplex.com/releases/view/47411 L

转--《从0到100:知乎网站架构变迁史 》

初期架构选型 在2010年10月真正开始动手做知乎这个产品时,包含李申申在内,最初只有两位工程师:到2010年12月份上线时,工程师是四个. 知乎的主力开发语言是Python.因为Python简单且强大,能够快速上手,开发效率高,而且社区活跃,团队成员也比较喜欢. 知乎使用的是Tornado框架.因为它支持异步,很适合做实时comet应用,而且简单轻量,学习成本低,再就是有FriendFeed 的成熟案例,Facebook 的社区支持.知乎的产品有个特性,就是希望跟浏览器端建立一个长连接,便于实

搜索题推荐

(转自网络博客): POJ POJ 1376 – Robot(基础) http://acm.pku.edu.cn/JudgeOnline/problem?id=1376 题意:略 解法:bfs,A*-. POJ 2688 – Cleaning Robot(基础) http://acm.pku.edu.cn/JudgeOnline/problem?id=2688 题意:bfs后转换为tsp问题 解法:bfs+dp,bfs+dfs 相关:http://hi.baidu.com/zfy0701/blo