京东商品搜索简介
京东商品搜索引擎是搜索推荐部自主研发的商品搜索引擎,主要功能是为海量京东用户提供精准、快速的购物体验。目前入口主要有PC/移动/微信/手Q搜索、移动列表页、店铺搜索、店铺列表等。虽然只有短短几年的时间,系统已经能够支持日均PV过亿的请求,并且经过了多次618店庆和双11的考验。
与人们日常使用的如谷歌、百度等大搜索(或称为“全文搜索”)引擎相比,京东商品搜索引擎与前者有相通之处,比如“覆盖海量数据”、“超高并发查询”以及“超快速的请求响应时间”,同时又有自身显著的业务特点:
正是由于既要兼顾大搜索引擎的通用需求,同时要契合京东的业务特点,我们将系统架构分为四个部分:1. 爬虫系统、2. 离线信息处理系统、3. 索引系统、4. 搜索服务系统。
为了使各位读者能够深入了解京东商品搜索引擎的架构,本文首先介绍了商品搜索的总体架构,然后依次介绍了爬虫系统、离线信息处理系统等各个部分,并且对搜索技术的最新研究方向做展望,希望对各位读者有所帮助。
总体架构
京东商品搜索引擎的整体架构如下图所示:
从上到下共分为3层。最上层是由搜索的前端UI层,负责页面展示。
中间层是由搜索索引服务、SUG搜索、相关搜索、划词服务和兜底服务组成。其中,SUG搜索提供输入框下拉提示词功能;相关搜索提供与query相关的其他搜索词服务;划词服务提供去除query部分词的功能;兜底服务用于索引服务异常情况下提供托底,保证用户基本的搜索可用。
最下层是索引生产端,主要功能是对接商品、库存、价格、促销、仓储等众多外部系统,整合相关数据生产全量和增量数据的索引,为在线检索服务集群提供全量索引和实时索引数据。
爬虫系统
商品搜索引擎的核心是建立商品索引,而建立索引需要详细的商品信息数据。我们利用大数据平台的数据库抽取接口和中间件系统,实现了站内商品爬虫系统,用来抽取数据库中的商品信息和及时发现变化的商品信息。从实践的效果上来看,爬虫系统表现是非常稳定和可靠的。
离线信息处理系统
离线信息处理系统主要功能是用来建立商品搜索引擎的待索引数据,包括全量待索引数据和增量待索引数据。
目前商品全量待索引数据按天进行更新,一部分是商品的基础属性信息,如商品sku、商品名称、颜色、规格、风格、材质面料等等,属于比较稳定、短时期内不会变化的数据。另外一部分是商品销售信息,如商品销量、销售额、评论等,属于易变数据。这些数据散布于多个系统中,使用的存储也各不相同。因此需要对这些来源分散的数据在商品维度进行合并,生成“商品全量待索引宽表”。目前我们建立的全量待索引宽表,不仅应用于搜索引擎服务,还同时应用于个性化推荐等其他产品服务当中。但是仅生成宽表是无法完成搜索引擎的索引需求的,因此我们利用Hadoop/MapReduce计算框架对宽表数据进行清洗,并且依照离线业务逻辑规则对数据进行二次“加工”,最终生成一份全量待索引数据。
有些商品信息,比如“价格”、“库存”、“上下架”等,经常会产生变化,因此对这些数据做全量索引满足不了商品搜索引擎的需求。为了解决数据实时性的强需求,我们建立了增量索引作为全量索引的补充。具体细节上,采用和全量索引类似的方法对数据进行处理,生成增量待索引数据。为了保证增量数据的及时性和准确性,离线信息处理系统会实时调用各商品信息接口获取数据,完成增量待索引数据的在线组装和生产。
索引系统
索引系统是商品搜索引擎的核心,主要功能是把以商品为维度进行存储的待索引数据,转换成以关键字为维度进行存储的数据,用于搜索引擎上层服务进行调用。这里待索引数据指前面离线信息处理系统生成的全量待索引数据和增量待索引数据。
此系统对于全量和增量的处理是一致的,唯一的区别在于待处理数据量的差异。一般情况下,全量数据索引由于数据量庞大,采用Hadoop/MapReduce进行;实时数据量小,采用单机进行索引生产。
为了满足分布式检索的需求,索引系统还会对索引数据进行分片处理,即按照一定策略将索引数据拆分成较小索引片,用于搜索服务系统调用。
搜索服务系统
搜索索引服务系统主要功能是接受用户请求并响应,返回搜索结果。搜索服务系统的发展也经历了从无到有,从简单到丰富到过程。主要分为如下几个阶段:
完整的搜索索引服务架构,如下图所示:
搜索请求流程如下:
Blender、Merger、Searcher和Detail是整个系统的核心组件,它们之间的调用关系由Clustermap管理。各个模块将自己的服务注册到ClusterMap,同时从ClusterMap订阅其调用模块的信息来确定实际调用关系。
简要搜索服务流程,如下图所示(搜索服务系统内部处理流程):
图中名词解释如下:
用户请求发送到blender,首先解析参数。如果命中blender page cache直接返回给用户。如果没有命中,则调用运营平台服务(OP)和QP,并将其传给Merger,Merge会检查是否命中Attr cache,如果命中并且恰好仅请求属性汇总结果,直接返回给blender。否则进一步查看是否命中merger page cahce,如果命中直接调用detail包装,返给blender。如果没有命中,则调用User Profile获取用户标签,将其传给searcher(篇幅所限,图中只列了一个searcher,实际是多个)。Searcher接到请求,判断是否命中doc cache,如果命中doc cache,则拉取增量结果;如果没有命中doc cahe,则拉取全量和增量结果。然后依次进行排序、在线业务处理,把结果返给merger。Merger合并多个searcher结果,排序、在线业务处理,最后调用detail包装,最后将结果返给blender,blender合并多个搜索结果后返回给用户。
作为一个高并发系统,为了保证高召回率和低响应延时,我们把整个搜索服务流程的处理全部放在内存当中进行计算。多个searcher并发处理请求,同时单个searcher内部采用线程池技术,即所有线程之间共享倒排索引和商品属性信息,提高内存使用效率;每个查询使用一个独立线程串行执行,保证并发的多个查询线程之间互不影响。此外通过合理的设置线程池的大小,我们可以保证系统的CPU资源得到充分利用。在上述两个方面对系统进行优化之后,整个搜索服务系统的稳定性、召回率、内存使用率、计算速度等指标都有大幅度的提高。但是我们改进系统的步伐并没有停歇,因为通过实践发现基于内存和线程池的搜索服务仍然有几个瓶颈点亟需解决,主要包括:拉取倒排、排序和在线业务处理。针对这些问题,我们进行了二次优化,主要包括如下措施:
1. 多级缓存策略
虽然拉取倒排结果缓存的key很快就解决了,但是我们在解决Value的存储时遇到了两个问题:1)拉取倒排的结果非常之多,导致缓存过大;2)对此结果缓存,会降低实时索引的时效性。
对于问题1),在分析了业务之后,对需要缓存的信息进行了大量的精简并采用压缩存储,最终将一个查询的缓存控制在0.5M以下。
对于问题2),我们将拉取倒排结果分为两部分,第一部分是从全量索引拉取倒排的结果,第二部分是从实时索引拉取倒排的结果。为了和全量索引的更新频率保持同步,我们把第一部分数据进行缓存的周期置为1天。对于第二部分数据,由于增量结果远远少于全量结果(一般增量只有全量5%不到),每次缓存都进行实时计算,这就是图3中的doc cache机制。从实践中来看,命中doc cache的响应时间比未命中的降低了1-2个数量级。将来随着增量结果的积累,如果实时拉取倒排结果成为性能瓶颈,可以对增量索引分段也进行缓存。
2. 截断策略
对于有些热门查询,由于其结果较多,比如“男装”、“鞋”之类的query,原始查询结果几千万个,如果对这些结果挨个进行处理,性能会非常差。同时,从用户角度分析,一个查询只有排在最前面的结果对用户才有意义。通过分析用户翻页次数,可以得到截断保留topN结果。如何保证截断不影响用户体验呢?首先我们对商品建立离线模型,即为每个商品计算出一个质量分数据。然后在索引阶段,将所有商品按照质量分降序排列,保证在倒排链中,排在前面的商品质量分总是高于后面的。在线从前往后拉取倒排过程中,如果结果数达到10*topN时,停止拉取倒排。随后对结果计算文本相关性,再按照文本相关性取topN个。截断算法上线前后,虽然KPI指标无明显变化,但是对大结果查询性能提升了一个数量级。
3. 均匀分片策略
从总体架构图中我们可以看到,如果我们将一个term的倒排链进行均分,那么相应term的拉取倒排也会被分配至各个searcher列。正是由于各个searcher列是并行计算的,这样的均分操作就可以大大减少每个查询的平均响应时间。从理论上来讲,我们采用的均匀分片策略,也有效的契合了拉取倒排、排序、在线业务处理等CPU密集型的任务。但是分片增加,会带来硬件成本增高的后果,同时集群节点间的通信成本也会增加,需要进一步权衡折衷。
4. 业务优化
京东的搜索业务并不只有上面所述的策略和工程逻辑,还必须融合很多业务逻辑。由于每一次搜索几乎都会召回很多结果,如果业务逻辑处理不好,也会导致搜索体验不好。针对这一问题并没有通用的解决方法,但是通过实践我们总结出一个基本原则:在离线阶段完成尽可能多的业务逻辑,减少在线计算量!例如进行搜索排序时,我们需要根据用户搜索历史行为(浏览、点击、购买等)对召回的结果进行排序上的调整,在工程实现上我们会先离线统计出同一个query下所有用户对每个展示商品的行为,然后建立模型,计算出该query下每个商品的权重,将其以hash结构存储;在线排序时,直接以query+商品id为key,取出权重作为反馈特征参与综合排序。
搜索技术的新发展
我们在当前的架构基础之上,正在进行一些新的探索,比如场景搜索和图像搜索。
场景搜索
随着目前京东集团的业务的扩展,用户在使用搜索时,目的不仅仅是查找商品,还可能查询促销活动信息。为了满足这些新的需求,我们在目前商品索引融合了促销系统的数据。我们首先在Query Processor中增加对应意图的识别,然后将促销等数据转换为索引数据。只要Query Processor识别出用户提出这方便的查询意图,将对应的结果返回。
图像搜索
传统搜索仅仅针对文字,但是电商系统的商品图片非常重要,很多购买决策依赖于它。目前我们利用deep learning技术离线训练图片特征,并将其做成索引。当用户使用实拍图或者网图来搜索时,采用相同的方式提取特征,然后从索引中召回最相似商品返回给用户。