Skip to content

Havenask介绍

xuxijie edited this page Oct 13, 2023 · 3 revisions

Havenask简介

Havenask是阿里巴巴自主研发的大规模分布式搜索引擎,主要专注于智能搜索和海量数据实时检索,其核心能力广泛应用于阿里巴巴内部的众多业务,如淘宝、天猫商品搜索,盒马搜索,菜鸟物流订单实时检索等。Havenask底层全部采用c++实现,并经过多年的优化迭代,与其他的开源搜索引擎相比具有如下特点:

高性能:查询性能高,某些场景性能数倍于开源引擎。

低成本:支持存算分离,冷热数据隔离等功能,海量数据场景下成本更低。

时效性高:数据写入或者更新的时效性可以达到毫秒级。

稳定性高:内存控制严格,没有其他开源引擎gc的问题,同时支持多机房互备具有更高的可靠性。

索引类型丰富:支持kv、kkv、倒排、正排、摘要、向量多种索引类型。

定制能力强:支持分词器、数据处理、query改写、算分、功能函数、等多种插件的定制。

支持SQL语法:支持sql查询,多表join,学习门槛低,业务迁移方便。

Havenask架构

Havenask引擎支持两种工作模式:读写分离模式(全量表模式)与读写统一模式(直写表模式),读写统一与读写分离的主要区别是是否有独立的索引构建服务,下面详细介绍。

读写分离架构

Havenask读写分离架构如上图所示,在此模式下索引构建系统与在线检索系统是两个独立的子系统,可以分别进行资源的调整和集群的管理,索引构建系统和在线检索系统通过消息中间件和分布式文件系统进行索引的交互。读写分离架构适用于需要快速导入全量数据,需要定期进行索引重建,数据更新量较大,需要对离线资源进行独立控制等场景。

索引构建系统

索引构建系统是一个分布式的索引构建服务(build service,简称bs),每个索引构建服务都有一个或多个bs admin,bs admin负责管理表的索引构建流程,其中每个表可以有多个索引构建流程同时存在,相互之间无影响。每个索引构建流程都由一组processor、builder、merger任务组成,其中processor负责原始数据的处理,比如分词,builder负责索引的构建,merger负责索引的整理。processor可以自由设置分片数,每个分片负责处理一部分数据,分片越多数据处理能力越强,使用的资源也越多。builder的分片数必须是索引表分片数的倍数,分片数越多索引构建越快。merger的分片数必须是索引表分片数的倍数,分片数越多索引整理越快。processor是一个常驻任务,builder和merger是交替执行的任务。

索引构建流程

读写分离架构下的表的数据索引构建由全量和实时两个阶段组成,同一个表可以同时存在多个索引构建流程,彼此之间无影响。全量阶段索引构建系统会将存在HDFS、MaxCompute或者OSS上的全量原始文件构建成全量索引,并订阅消息中间件回追一部分实时数据(防止全量切上线之后需要很长时间才能追上实时数据)。索引构建过程中,processor会读取原始数据并对齐按照配置的数据处理规则进行处理,处理之后的数据会被发送到消息中间件(swift)。builder订阅消息中间件,将处理之后的文档构建成索引,并将索引产出到分布式文件系统。消息中间件中全量阶段处理的数据被builder全部处理完后,启动merger任务对索引进行整理,产出全量索引。

全量阶段完成后,全量索引会被切换到在线系统,同时索引构建也切换到增量阶段。增量阶段processor订阅消息中间件,处理实时数据,并将处理好的数据写回消息中间件。在线系统同时订阅消息中间件,获取处理之后的文件,直接在内存中构建成索引,这样数据就可以实时生效。builder也会订阅消息中间件,获取处理之后的文件,将其构建为增量索引,并由merger对全量索引和增量索引进行索引整理,产出最终可以切换上线的索引。增量索引切换上线之后,在线系统实时中的实时索引会被从内存中清理掉,释放的内存会被用于构建新的实时索引。

在线系统

在线系统用于加载索引并提供检索服务,它是一个支持多分片(shard),多备份(replica)部署的分布式服务,主要由admin,qrs(query result service)和searcher(数据节点)三种角色组成。Admin管理整个集群,实时监控各个节点的健康状态并调度,接收运维命令并向qrs和searcher下发运维指令。Qrs用于query的处理和结果的合并,qrs没有分片的概念,每个qrs节点都是同构的。Searcher节点加载索引,并真正执行查询任务,searcher节点上可以加载一个表的一个分片或者多个分片的数据。

在Havenask中用区间[0, 65535]表示一份完整的数据,所有的数据分区键经过哈希之后都会映射到[0, 65535]这个区间之内。在设置表的分片数之后,每个分片都会对应这个区间的一段范围,比如分片数为2,分成的两个分片对应的区间为[0, 32767]和[32768, 65535]。Havenask单分片最多可以承载21亿个文档,所以分片数越多,整个集群可以承载的数据量越多,最多支持65536个分片。

Qrs和searcher都可以通过扩充备份来提高整个集群每秒query处理能力(qps),不同的是qrs没有分片的概念,扩充备份就是扩qrs节点的个数,searcher是按照分片组织的,在每个searcher加载一个分片前提下,扩searcher的备份数就是扩分片数*备份数个searcher节点。

Havenask支持存算分离,Searcher上的索引加载采用远端分布式文件系统、本地磁盘和内存三级索引加载策略,索引读取的性能也是按照远端、本地、内存这个顺序有数量级的提高。开发者在使用时可以综合考虑成本与查询耗时的要求,合理的配置索引加载策略。

读写统一架构

Havenask读写统一架构如上图所示,与读写分离架构相比有下面几个不同点:1)读写统一模式没有全量流程,所有的数据都要通过api以实时生效的方式推送到系统中;2)实时数据的推送直接写入到qrs,而不是swift中;3)每个分片对应searcher的leader进行索引整理,并将整理好的索引写入分布式系统中,follower加载整理好的索引。读写统一架构中使用swift进行wal以保证数据的安全,swift做wal的好处是不会随着searher备份的增多导致写的性能下降。读写统一架构比较适合频繁创建索引表、不需要全量数据导入、时效性要求高等场景。

Havenask索引类型

Havenask主要有三种类型的索引:倒排索引,正排索引与摘要索引。

倒排索引

倒排索引存储的是词(term)到包含词的文档(doc)的映射关系,可以通过倒排索引快速的检索到需要的候选文档,如下图所示。

Havenask支持多种类型的倒排索引,比如主键索引,STRING索引(keyword,不分词),多字段PACK索引,数值范围索引,空间索引等,具体每个索引的含义开发者可以参考Havenask的用户手册。

向量索引(ANN)是一种特殊类型的倒排索引,它的索引结构与上图的通用倒排索引结构不同,具体的构建方式与索引结构和向量索引选择的算法有关。Havenask支持的向量索引有三种类型,线性索引、HNSW索引和聚类索引,可以满足不同场景下的向量检索需求。

正排索引

正排索引存储的是文档中字段的内容,主要用于对查询到的结果进行过滤、统计、排序等操作。Havenask的正排索引采用的是列存模式,即每个字段单独存储,如下图所示。

摘要索引

摘要索引存储的是文档中需要返回的字段,可以对返回的字段进行飘红处理,如果字段内容较长可以使用摘要插件动态截取要返回的内容。Havenask的摘要索引采用的是行存模式,即一个文档的所有字段存在一起,如下图所示。

Havenask查询语法

Havenask目前支持sql查询语法,sql语法简单易用并且便于扩展。但是具体到检索场景,sql语法还是有些不足,比如查询时的多索引倒排搜索,粗排与精排的支持等。为了弥补搜索场景下sql能力的不足,havenask提供丰富的各种内置函数,比如提供了MATCHINDEX和QUERY等UDF支持倒排索引的查询,并支持自定义UDF。

Havenask插件机制

Havenask支持开发者自定义分析器插件、数据处理插件,各类UDF等以满足不同的业务需求。

分析器插件:开发者可以通过分析器插件定制自己的分析器,以满足不同的分词需求。分析器插件作用在数据处理分词阶段和查询时Query分词阶段。

数据处理插件:在构建索引之前,需要对文档进行处理(默认的是分词),开发者可以通过定制自己的数据处理插件提前对数据进行处理,比如可以集成一个向量化模型,在数据处理阶段将文本转为向量。

UDF:用户自定义函数,在查询时通过UDF可以定制自己的业务逻辑,比如外卖场景下,计算店铺和买家的距离。

对于各种定制插件,我们推荐开发者不要将插件代码单独编译成so的形式,而是与Havenask代码一起编成一个统一的binary,通过镜像的方式发布。

Havenask运维管控

Havenask的各个子系统(在线系统,索引构建系统,消息中间件)都有对应的admin角色进行集群的管理,每个admin都提供了运维管控的rpc接口。为了方便大家的使用,我们对这些rpc接口进行了封装,提供了方便使用的命令行工具hape。使用hape,开发者可以方便的启停集群,对表进行各种管理操作,如果需要更精细的运维控制,开发者可以直接调用admin提供的rpc接口。

Clone this wiki locally