阿里巴巴搜索引擎平台 Ha3 揭秘
云栖君导读: Ha3 是阿里巴巴搜索团队开发的搜索引擎平台,它为阿里集团包括淘宝、天猫在内的核心业务提供搜索服务支持。
Ha3 的架构
在线
Ha3 是搜索体系中的在线部分,在其系统内部,包含 Qrs(Query result searcher) 和 Searcher 两种基本的角色。
Qrs 用于接收用户查询,将用户查询分发给 Searcher,收集 Searcher 返回的结果作整合,最终返回给用户,这里的用户既指直接通过 http 请求查询引擎的自然人,也指 Ha3 的上游服务,如 sp(搜索链路的 Ha3 上游服务) 和 tpp(推荐链路的 Ha3 上游服务)。
Searcher 是搜索查询的执行者,倒排索引召回、统计、条件过滤、文档打分及排序及摘要生成的过程都是在 Searcher 上完成的。根据业务的需要,有时也会把摘要 (Summary) 单独分出来,搭建一套独立的摘要集群。
在实际的部署中,Qrs 和 Searcher 都是采用多行部署的方式,可以根据业务的流量变化作调整。Searcher 还可以根据业务的数据量调整列数,解决单机内存或磁盘放不下所有数据的问题。
Qrs 和 Searcher 都可以通过运维系统挂载到发现服务上,这里提到的发现服务通常是 cm2 和 vipserver。结合 gig 这个搜索团队开发的 RPC lib,对 Qrs 和 Searcher 的访问均可以做到自动的流量均衡及坏节点检测降级,达到业务上的平稳运行。
离线
我们把索引数据的生成过程称作离线过程。Ha3 的索引是通过搜索团队开发的 Build Service 系统生成的。
Build Service 首先是一个独立的服务,通过运维系统对数据源产出的信号监控,这个独立服务产出全量和增量索引到 hdfs 上,通过 dp 分发给 Ha3 的 Searcher。全量索引的产出周期通常是一天或数天,增量索引的周期通常是几十分钟。
Build Service 也以 lib 的方式存在于 Ha3 当中,用于实时处理增量消息,直接将索引生成到 Ha3 Searcher 的内存当中,这样,Ha3 的查询结果对数据时效性的保证能做到秒级。但这种方式也比较耗内存,随着实时消息的到来作线性增长,因此每次加载增量索引时,Ha3 都会清理实时索引的内存。
table、zone、biz
从业务的角度,Ha3 包括 zone、biz、table 的概念
table 是数据表,Ha3 中一个 zone 必须包括一张主表 (item_table),有时也会包括辅表,辅表在数量上没有限制。辅表数据是对主表的补充,在线查询时 Searcher 通过配置中指定的字段,将主表和辅表的结果连接(join) 到一起返回给用户。在某些业务场景下,对主表中的文档,又会有进一步划分的需要,于是这里面还存在一个子文档 (subdoc) 的概念,供一些特殊业务使用,子文档在本文先不展开说明
业务配置 (biz) 描述了前文提到的 Qrs 及 Searcher 上的统计、算分、排序、摘要等多个环节。单集群多 biz,可以满足例如 ABTest 的需要
zone 是用于将多个 biz 与多个 table 作业务上的划分而存在的概念,它和 biz、table 的关系均是一对多。
查询时,用户需要填入 zone 的名称和 zone 下的 biz 名称,来指定执行对应 zone 下的业务逻辑,zone 是必须要指定的,而 biz 在用户没指定的情况下,使用默认 (default) 的业务配置
在线流程
在线流程中,用户访问 Ha3 的方式是向多行部署的其中一个 Qrs 发送请求,而 Qrs 的选择是通过发现服务配合流量均衡策略实现的。一个完整的请求会包含查询关键词,并且会包含描述了统计、过滤、排序的行为参数。Qrs 会再次通过发现服务结合流量均衡策略,选择具体的一列或多列 Searcher 机器,将用户查询分发下去。Searcher 上执行索引查找、过滤、统计,这些流程的具体行为与相关参数在查询和配置中均会有涉及。
Qrs
Qrs 上的查询逻辑相对于 Searcher 来说比较简单。一次完整的查询分为两个阶段:一阶段与二阶段。一阶段 Qrs 会向一个完整行的多列 Searcher 发送请求,从多列 Searcher 中拿到结果后作合并与排序,而二阶段则是将排序后,前 N 个文档 (这里的 N 由用户指定) 的 docid 或者 primary_key 拼到查询串中,送回给 Searcher 作摘要 (Summary) 查询,拿到多列摘要 (Summary) 结果后再做一次结果合并,返回给用户
Searcher
Searcher 的在线查询流程步骤较多,主要是以下几个部分:
Seek: 倒排索引的召回、合并与求交等操作
Filter: 对用户指定的条件将倒排召回的结果集再过滤一遍,剔除不满足条件的文档
Rank: 粗排算分,这里的算分过程耗时通常较少,但参与计算的文档量巨大,经过这一步后,得分靠前的文档会被保留,其余都会被删除,具体保留多少文档由用户的配置或查询条件决定,通常与参与 Rank 的文档有数量级上的差距
Agg: 对结果集的统计,统计的内容依据用户的查询条件决定
Rerank: 精排算分,到这一步,参与算分的文档与 Rank 过程有数量级上的差距,而计算逻辑较为复杂
ExtraRank: 返回给 Qrs 前的最终排序
一个典型的业务查询流程
我将用下图说明我们的一个实际业务在查询中与 Ha3 的交互过程:
搜索入口访问图中的 Ha3 上游,Ha3 上游在请求 Ha3 前,会根据需要 (如用户个性化信息、查询词扩展、类目预测等等) 生成 Ha3 查询串,请求 Ha3
Ha3 的 Searcher 部分按文档质量,依次切分成 zone1、zone2、zone3,Ha3 上游会设定一个预期返回的文档个数阈值,先请求 zone1,当 zone1 召回的文档数不满足阈值时,会继续查询 zone2,仍不够时,则会再次查询 zone3
第 3 步完成后,上游会将 Ha3 召回的文档送到算分集群中用更为复杂的算法模型进行算分,从算分集群拿到结果后,上游会取排名前列的文档,向 Ha3 的 Summary 获取这些文档的摘要信息,返回给搜索前端
离线流程
离线流程的执行者 Build Service,负责将纯文本的商品数据构建成 Ha3 格式的索引文件。原始的商品数据有两类,一类是存放在 hdfs 上的全量商品数据,这个定期 (一般以天为周期) 由业务方产出,另一类为实时增量数据,在商品信息变更后,由业务方即时同步给消息系统 swift。为了高效稳定地将全量和增量数据产出给 Ha3,Build Service 被设计成了由 3 个角色组成。
Build Service 的 3 个角色
Processor: 对原始文档的文本处理,包括业务逻辑对字段内容的改写与分词
Builder: 将原始文档转化,产出索引格式的数据
Merger: 将 Builder 产出的索引数据作合并,产出为最终被 Searcher 加载的索引文件
全量索引的产出
全量流程的输入数据是存放在 hdfs 上的原始文档。全量索引的 build 流程包括手动触发与自动触发。手动触发就是由集群的管理者通过运维系统管控页面触发。自动触发则是由运维系统定期扫描 zk server 上的路径监听新数据产出的信号触发。
hdfs 上的数据经过 Processor 处理后送到 swift 的中转 topic 中
Builder 从中转 Topic 中拿到经过 Processor 处理的文档,生成索引数据后放到 hdfs 中
Merge 从 hdfs 上拿到生成好的索引数据,Merge 成各列 Searcher 上能够加载的索引文件
Merge 过程完成后,运维系统调用 dp 将其分发到 Searcher 所在的本地磁盘上
增量索引的产出
增量与全量流程的不同之处在于数据源。与全量数据源为 hdfs 不同,增量的数据源是由数据产出方每时每刻都在发送的增量消息,这类消息经过 swift 的原始 topic 后,再经由 Processor 处理,之后的流程就和全量索引产出的流程相同了。增量索引会定期地分发到 Searcher 的磁盘上
实时索引
实时索引的数据源和增量索引一样,是数据产出方发送的 swift 消息。与增量不同的是,增量是产出数据到 hdfs 上,通过定期分发供 Searcher 加载,而实时索引,是通过中转 Topic,经由以 lib 形式存在的 Realtime Builder 处理后,直接放到 Ha3 内存中。增量索引的时效性跟配置的生成周期有关,通常是几十分钟,而实时索引的时效性是秒级的。在新的增量索引加载后,Ha3 会对实时索引作清理
插件机制
为了实现业务的可定制化,Ha3 提供了插件机制。在前文介绍的离线和在线流程的各个环节中,Ha3 用户可以通过开发自己的插件,对原始文档、查询 Query、召回、算分、排序、摘要做业务上所期望的修改。
运维
Ha3 的日常运维包括二进制版本更新、配置更新、全量与增量索引更新、扩行扩列、机器调度分配等。这些都是通过简易的 web 操作,后端子模块相互配合完成的,避免了全手工操作的琐碎而又容易出错的细节。实现运维环节的子模块包含以下几个:
suez_ops: 这是线上运维操作的入口,其后台将 build service、swift、ha3 和离线产出做全流程的对接,配置的更新、回滚、扩行扩列、资源调整等均能在 suez_ops 的 web 页面上操作,对于在交互和 web 上有强定制需求的用户,suez_ops 也提供了 API,以供进一步开发
suez admin: 这是一个承上启下的角色。用户通过 suez_ops 的操作提交自己的运维需求,ha3 admin 拿到更新信息后,将更新目标分解,发给自己管理的 Qrs 或 Searcher worker,具体的变更行为由 Qrs 或 Searcher 进程自己完成
carbon: 是内嵌在 suez admin 中,以 lib 存在的调度框架,一方面收集下游 worker(Qrs/Searcher) 的状态,如是死是活、是否已经到达了目标状态,另一方面调度具体的 worker 来执行
让用户无感知的在线服务更新,是通过灰度 (rolling) 的方式实现的。在多行部署的前提下,通过用户配置的最小服务比例 (minHealthRatio) 参数,carbon 选择合适的行数进行更新。如果当前机器不够,则会申请新的机器以凑够足够的行数,待这些机器上都成功升级后,再选下一组机器继续升级。至于升级过程中是否停流量,可以在目标中设置是否由 carbon 停流量,不过在 suez 中,都是 worker 自己决定的。对于 ha3, 除了 binary 更新、内存不够情况下的 forceLoad, 都是不停流量升级的
时间:2018-12-02 23:42 来源: 转发量:次
声明:本站部分作品是由网友自主投稿和发布、编辑整理上传,对此类作品本站仅提供交流平台,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,不为其版权负责。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。
相关文章:
相关推荐:
网友评论: