加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

异构数据半小时实现搜索功能,一个系统搞定

发布时间:2019-08-29 08:44:58 所属栏目:建站 来源:峰明
导读:背景 对于闲鱼这种处于高速增长期的部门来说,业务场景在快速膨胀,越来越多的业务数据对搜索能力有诉求。如果按照常规的方式为各个业务搭建独立搜索引擎服务,那么开发和维护的时间成本将是非常巨大的。能否只用一套搜索引擎系统支撑不同业务场景产出的数
副标题[/!--empirenews.page--]

背景

对于闲鱼这种处于高速增长期的部门来说,业务场景在快速膨胀,越来越多的业务数据对搜索能力有诉求。如果按照常规的方式为各个业务搭建独立搜索引擎服务,那么开发和维护的时间成本将是非常巨大的。能否只用一套搜索引擎系统支撑不同业务场景产出的数据呢?不同场景的异构数据如何在一套引擎中兼容呢?闲鱼从实际的业务需求出发,搭建了一套通用搜索系统解决这个问题。

异构数据半小时实现搜索功能,一个系统搞定

搜索原理简述

闲鱼使用的搜索引擎是阿里巴巴的HA3引擎,配合其上层的管控系统Tisplus2使用。可以拆分为以下几个子系统:

1、dump:接入搜索系统首先要做的就是把DB数据经过一些业务逻辑转换后(后面会详细描述的merge、join流程),按照引擎BuildService能够识别的文件格式写入到文件系统或者消息队列中供BS构建索引使用,这个过程分为全量与增量两种。

2、BuildService(简称BS):将dump产出的数据构建成索引文件。Searcher机器加载了BS产出的索引文件后才能提供倒排、正排、summary的查询服务。

3、搜索业务网关:业务层封装统一服务接口,对业务接入方屏蔽搜索系统底层细节。

4、Search Planner(简称SP):组合搜索中台多种能力,调用算法服务对网关传入的查询串进行改写、类目预测、算分,实现多路召回、分层查询、翻页去重等功能,对QRS返回的结果进行包装返回。

5、引擎在线服务:分为QRS与Searcher两种角色。SP的查询请求发送给QRS,QRS将请求转发到多台searcher机器上然后收集searcher返回的结果进行合并、算分、排序、返回。

整个搜索系统的简化版结构图如下:

pic1

为每个业务场景从头搭建一套搜索系统是有一定复杂度的,而且需要花费较多时间。我们希望提供一套通用搜索系统,当新的业务数据接入搜索能力时,不需要业务开发同学精通搜索系统原理,只要在我们的系统中注册哪些数据需要被搜索,就可以完成搜索能力的自主接入,几乎无需开发,真正实现十分钟快速接入搜索。多个业务的数据共存在一套搜索引擎服务中,各业务数据相互隔离互不影响。

这里涉及到两个问题:

①如何把异构数据从不同的业务db写入同一个引擎构建索引,且写入过程完全自动化、透明化,无需业务接入方参与开发;

②如何实现不同业务场景的开发同学在使用搜索召回的过程中不感知到其他业务数据的存在,就像在使用一套为他的业务单独搭建的引擎服务一样方便。

我们的解法

针对上面遇到的2个问题,我们的解决思路是提前构建一套通用搜索系统,把dump、bs、search、Search Planner、网关层的基本能力都提前实现,业务在调用服务时通过设定可选的入参来选择自己需要的能力(比如关键词改写、类目预测、pvlog打印、分层召回等)。通过一个中间层把dump流程自动化,并对dump、search过程进行字段翻译、结果包装。

搜索引擎基本服务的搭建过程与常规方式无大的差异,这里不详细描述。接下来我详细介绍一下此方案实施过程中拆分出的4个技术要点:①通用搜索预留表;②元数据注册中心;③两层dump;④在线查询服务。

1、通用搜索预留表

常规情况下,我们会把dump产出的大宽表字段命名为itemId、title、price、userId等具有明确语义的字段名。但是如果要实现多场景共用一套引擎就不能这么做了,因为并不是所有场景数据都有itemId、title、price字段,也可能某个场景中需要接入color字段但是我们的引擎中没有定义这个字段,导致无法支持这个业务场景。

既然问题的关键是字段定义有语义,那么我们解决这个问题的思路就是让已引擎中的所有字段都完全无语义,只有类型信息。我们按照下图的方式预定义2个维度,每个维度下各2张Mysql表和2张ODPS表(这种定义已经可以覆盖绝大多数场景了),称为通用搜索预留表。

pic2

为每张预留表预留各种类型的字段,按照所处维度、表在维度内位置、字段类型进行字段命名:

1)将第一个维度中第一张预留表表的字段命名为dima_pk、dima_a_int_r1、dima_a_text_multilevel_r1、dima_dimb_joinkey等;

2)将第一个维度中第二张预留表表命名为dima_b_inner_mergekey、dima_b_int_r1、dima_b_int_r2、dima_b_long_r1等;

3)将第二个维度中第一张预留表表字段命名为dimb_pk、dimb_a_int_r1等;

4)将第二个维度中第二张预留表表命名为dimb_b_inner_mergekey、dimb_b_int_r1、dimb_b_long_r1等;

然后将预留表按照上图的结构,与引擎原生的dump系统进行对接,并配置索引构建信息。当这套引擎服务搭建完成后,如果直接往通用搜索预留表中接入几条数据,就已经可以从引擎在线查询接口中查到数据了。不过这套搜索系统对业务开发同学来说是不可用的,因为业务源表结果与我们的预留表结构完全不同,业务同学很难把数据从源表按照我们预定义的格式全部迁移到通用搜索预留表,且查询时用“dima_a_text_multilevel_r1='iPhone6S'”这种无语义的方式做查询也是业务同学无法接受的。接下来我们就来解决这些问题。

2、元数据注册中心

我们设计了一个元数据注册中心,当一个新业务需要接入搜索能力时,只需要在注册中心填写业务相关注册信息(包括业务场景标签,需要接入搜索能力的数据库、表名、字段等基本信息),系统会分配一个业务唯一识别码,这个识别码会作为dump、bs、查询流程中实现多业务隔离的最重要标识。

元数据注册表结构:

table

元数据注册中心以WEB界面形式提供新业务注册的能力,用户在填写业务的库名,会通过中间件自动拉取到包含的所有表名。用户从中选择自己需要接入的表名,界面上列出此表下的全部字段,以及系统预设的全部通用搜索预留表字段。用户在源表字段与预留表字段之间用鼠标建立连线,完成后点击提交,系统将对用户建立的映射关系进行各项合法性检查,检查通过后按照上面的元数据注册表结构写入DB。这份注册数据以后将在dump、查询等多个环节用到。

3、两层dump

每一张业务源表的语义一般比较单一,多张表组合在一起才能够形成一个业务场景的全貌。比如:

1)商品基本信息表中会存储商品id、标题、描述、图片、卖家id等信息;

2)商品扩展信息表中会以商品id为主键,存储商品扩展信息,如sku信息、扩展标签信息等;

3)卖家基本信息表中会以用户id为主键,存储用户的昵称、头像等基本信息;

4)卖家信用信息表中会以用户id为主键,存储用户的芝麻信用等级。

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读