欢迎您光临本小站。希望您在这里可以找到自己想要的信息。。。

蘑菇街搜索与推荐架构,从 0 到 1 再到 100

架构&设计模式 water 2906℃ 0评论

本文分享蘑菇街在搜索与推荐上踩过的坑,以及在探索路上的经验总结。从 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 ~ 2016.3)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 时期的推荐架构

从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 & 强化学习,根据算法效果来设计新产品。

丁小明,花名小宝

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

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

转载请注明:学时网 » 蘑菇街搜索与推荐架构,从 0 到 1 再到 100

喜欢 (1)or分享 (0)

您必须 登录 才能发表评论!