10 | 索引拆分:大规模检索系统如何使用分布式技术加速检索?
该思维导图由 AI 生成,仅供参考
简单的分布式结构是什么样的?
- 深入了解
- 翻译
- 解释
- 总结
大规模检索系统如何使用分布式技术加速检索? 分布式技术在大规模检索系统中扮演着关键角色,通过将任务分解并利用多台服务器共同承担任务,提升整体系统的服务能力。文章介绍了简单的分布式结构以及基于业务、文档和关键词进行索引拆分的方法,以加速检索效率。 在简单的分布式检索系统中,分发服务器负责任务分发,而多台索引服务器执行具体的检索任务,从而大幅提升整个检索系统的处理能力。然而,这种简单的分布式系统只能提升检索系统整体的“吞吐量”,而不能缩短一个查询的检索时间。 为了提升单次检索的效率,可以将倒排索引拆分并分散加载到每台服务器的内存中,从而避免或减少磁盘访问,提升单次检索的效率。基于业务的拆分和基于文档的拆分是实用的索引拆分方案,但也存在一定的耦合性和管理问题。 另一种拆分方案是基于关键词进行拆分,将词典划分成多个分片,分别加载到不同的索引服务器上。这种方案在查询词少的情况下能大幅降低请求复制的代价,但也带来了复杂的管理问题。 综合来看,基于文档的索引拆分是一种更通用、扩展性和可运维性更好的方案,能够提升检索效率并适用于大多数场景。 通过本文的总结,读者可以快速了解大规模检索系统如何使用分布式技术加速检索,以及不同的索引拆分方案的优缺点,为设计和优化分布式检索系统提供了有益的参考。
《检索技术核心 20 讲》,新⼈⾸单¥59
全部留言(20)
- 最新
- 精选
- 无形先来回答老师的问题,基于文档拆分的方案,1,新增数据会落到某个具体的服务器,不需要考虑数据在所有检索服务器之间同步、不一致的问题,2,由于所有的检索服务器之间数据是均衡分布的,不存在服务器之间检索负载不均衡的问题 索引水平拆分垂直拆分和数据库的水平拆分和垂直拆分是类似的 我理解文档拆分是把数据对一个整体进行分片,对整体的查询变成了并行在分片上查询,缩短了查询时间,还有一个好处是新的文档被哈希到到某个分片上,对查询结果的影响被限定到这个具体的分片,不会影响所有分片 关键词拆分也是把整体分片,对整体的查询变成了在单个分片上的查询,如果有热点数据会导致posting list过大,降低查询效率,这里能不能特殊处理,给热点数据指定专门的更高性能检索服务器,提升查询效率
作者回复: 回答和总结得很仔细。 关于基于关键词拆分,能否特殊处理热点的问题,当然是可以的。如果查询热点一直比较稳定的话,我们可以通过加缓存,加副本,升级机器等方案来优化。不过一般来说,升级机器这种方案用得比较少,因为这涉及到更多的运维团队的工作,不如增加查询缓存,或者增加副本机器等机器调度方案便捷。
2020-04-234 - 奕Redis Cluster 技术相当于按照关键词进行拆分,直接定位到 要查询的 key 在哪个 slot
作者回复: 你举的这个例子很有意思。其实Redis cluster是一个kv存储,而不是一个倒排索引。对于kv,你既可以说它是按关键词拆分的,也可以说是按文档拆分的。 当然,如果kv中的v是一个结果集合列表的话,这就是一个典型的基于关键词拆分的倒排索引了。在我们不需要进行多个关键词合并的场景下,这样的使用方案是很适合的。
2020-04-1723 - 每天晒白牙# 提高的吞吐量而非检索效率 简单的分布式检索系统是指每台索引服务器保存了全量的索引数据,然后加机器,这种方式只能提高系统整体的"吞吐量",而不能缩短检索时间从而加速检索效率 # 通过拆分提高检索效率 检索时间与数据规模正相关,所以采用索引拆分可以加入检索效率 # 如何拆分? ## 基于文档拆分 核心思想是把大规模的文档集合随机拆分成多个小规模文档集合,即建了多个倒排索引,但每个倒排索引就是一个索引分片,保存了部分数据,所以它的 postinglist 不会太长,可以提升单机的检索效率 ## 基于文档拆分的检索流程 - 分发服务器接受查询请求,然后将请求分发给其他索引服务器 - 每台服务器根据自己加载的索引分片数据进行检索,再把结果返回给分发服务器 - 分发服务器将所有返回结果进行合并,返回给客户端 ## 基于文档拆分的优缺点 优点 1.基于随机划分,每个索引分片大小相近,在索引空间分配上是相对均衡的,而且每台索引服务器的负载也相对均衡 2.通过设置合理的分片数,有可能把所有数据加载到内存中,同时因为每个索引分片数据不大,可以提升检索效率 不足 分片数不能设置太大 因为客户端发过来的请求是先经过分发服务器的,然后转发给其他索引分片服务器,如果分片数过多,会设计很多网络 IO 操作,性能就会下降 ## 基于关键词拆分 通过关键词进行拆分是将不同的关键词放到不同的索引分片上,然后加载到不同的服务器上,这样的拆分方式可以达到每台索引服务器上的文档不是完整的,但关键词对应的列表是完整的 ## 基于关键词拆分的检索流程 客户端发来请求,如果只有一个关键词,那只需要查询改关键词所在的索引服务器就可以得到完整的文档列表,省去了分发造成的网络 IO 如果是多个关键词,可能也会发生分发请求,然后分发服务器合并请求返回给客户端 ## 基于关键词拆分的优缺点 优点 适合查询词少的情况,可以减少分发造成的网络 IO 不足 1.如果查询词比较多且没有被划分到一个分片中,也会分发请求,有网络 IO 2.如果关键词是高频热点词,那它对应的文档列表会非常长,检索性能也会下降 3.高频热点词所在服务器负载高,低频词所在服务器负载低,导致索引服务器负载不均衡 4.如果有新增文档,会涉及到多台索引服务器修改 # 思考题 ## 为什么说基于文档拆分比关键词拆分更好维护? 其实在上面分析两种方案的优缺点时已经介绍了,下面就简单总结下 - 当有新文档加入时,最糟糕情况会修改所有的索引服务器 - 遇到高频热点词,大量查询都打到了这个热点词所在的服务器上,导致该服务器负载很高,完成索引服务器的负载不均衡
作者回复: 总结得很好。我觉得可以给你补两个问题。有精力的童鞋也都可以想想。 1.如果索引是使用“全量索引+增量索引”,再基于文档拆分,那么一个新文档加入时,它是会加入到所有索引服务器的增量索引中,还是可以只加入到一台服务器的增量索引中? 2.基于文档拆分,会造成查询请求被复制多份,那除了基于关键词拆分,我们使用业务拆分的方案是否也能避免这个问题?
2020-04-1723 - new life按文档划分和按关键词划分,各有利弊 按文档划分: 1、一个关键词的所有文档分布在多个服务器上,缩短了每台服务器postlist的长度,提升了单台服务器的检索效率; 2、但是检索对外时候需要检索多台服务器,合并检索结果,增加了分页检索实现的难度; 按关键词划分 1、每台服务器上含有这个关键词所有的文档,检索的时候,只要找到对应的服务器,检索一次就行,不用结果合并,分页控制也好实现; 2、但是一个关键词的文档id列表放一块,提高了每次查询的检索成本,尤其是热点数据的检索时候,总要受不常用数据的拖累 思考题 我理解插入文档的时候,文档拆分和关键词拆分影响的都是一台服务器,热点数据检索的时候,关键词、文档拆分这种方式都是负载是均衡的,这也体现出按文档拆分的优势;
作者回复: 总结得很好。尤其你还提到了分页检索,这的确也是一个难点。基于文档拆分的方式需要解决问题。 至于思考题,在更新一个文档的时候,如果是基于关键词拆分的话,由于一篇文档中会有多个关键词,这些关键词可能是分布在不同的服务器上的,因此会影响多台服务器。 至于热点查询问题,如果是基于文档拆分,那么负载会更容易均衡到多台服务器上,避免热点。如果真有热点发生时,也可以灵活地重新分片进行负载均衡。因此会比基于关键词拆分更灵活。
2020-05-012 - paulhaoyi老师您好,请教一个问题,可能不一定和本章有关。我们做内容分发,需要再召回源拿出内容后,过滤用户读过的文章。由于量比较大,有些用户的阅读历史又很长,单独每个用户记录已读列表,不管是容量还是过滤性能都不太能接受。感觉这就是一个判断是否存在的问题。如果我用文章id做key,用户做的文档。建立倒排合适么?或者老师有什么好的方法建议?
作者回复: 其实对于这种是否存在的过滤问题,第四讲中我提到过,可以使用bloomfilter来进行判断文章是否已读。这样在容量和查询性能上都不错。缺点就是可能会有一定的错误率。不过作为内容分发场景而言,错判的话,只是少分发一个内容而已,应该是可以接受的。 如果不希望有错误率,那么可以使用加餐1中我提到过的roaring bitmap来进行查找。 至于你说的用文章ID为key,用户作为posting list的方案,我的理解是这个也是可行的。但是其实它和以用户为key,文章为posting list的方案的存储空间是一样的。你可以画一个矩阵,每一行是一个用户,每一列是一个文章。那么这个矩阵横着就是以用户ID为key,以文章ID为posting list的倒排;竖着就变成了以文章ID为key,以用户ID为posting list的倒排,因此并不会省空间。
2020-05-121 - 峰本来按照题目写了下答案,但感觉还不如跳出来回答这个问题,看着太像传统数据库横向拆分纵向拆分,然后引入中间件,然后就有手工分库分表那一坨解决方案。跳出这个思路,横向纵向分片只是分散数据到各个节点的手段,上层应该提供策略屏蔽这些手段的差异,针对具体的分片方式做优化,比如热点,那就针对这个分片多点副本。
作者回复: 是的。后面抽象成了水平拆分和垂直拆分,其实就和数据库的拆分理念很相似了。包括业务拆分,其实也和分库很相似。因此,许多设计理念都是可以相互借鉴,融会贯通的。
2020-04-171 - 那时刻尝试回答老师在回复里的问题。不明白的地方请老师指正。 1.按文档拆分,新增加的文档可以只加到一台增量索引的机器上班,因为查询的时候有按照关键字的合并 2.我觉得可以按照业务拆分来减少查询的复制,比如按照文档类型 军事,娱乐来把文档分区,这样查询关键字的时候,比如这个关键字属于军事类型就只去军事类型文档分区找就可以了。
作者回复: 1.没错。如果使用了全量索引+增量索引机制的话,对于新增文档,其实只需要先分片到对应的索引服务器上,然后加入这台服务器的增量索引即可。 2.业务拆分尽管和业务耦合紧密,不过它可以同时兼具文档拆分和关键词拆分的优点(也可以理解为,业务拆分可以在两个方向进行抽象,分别变成文档拆分和关键词拆分)。 业务既能对文档进行分片,也能在查询时指定只去一个分片查询,而不是所有分片都查询。因此在一些简单的应用场合中也是可以考虑的。 对应到数据库设计,就是分库的问题。
2020-04-171 - 那时刻基于文档或关键字拆分,类似于数据库的分库分表操作。基于文档拆分的好处在于分摊网络和io的压力。
作者回复: 是的。你会看到,数据库的分库分表其实也是一样的思路。因此,也希望大家能将一个技术进行横行对比,这样能更好地融会贯通,举一反三。
2020-04-171 - _你说了不算老师,我们的广告投放引擎在数据检索这块就走了不少路,es过滤和内存过滤两种方式都用过,最终还是用了内存过滤,原因是后者服务器的cpu和内存状态更好,不知道是不是我们用es的姿势不对。最近引擎系统cpu一直报警,除了加机器,就是加机器,想请教下老师,有遇到过类似的这种情况吗?假如按照文章中提到的索引拆分的方式,具体的落地方案老师能不能指点一二?还有我们的数据是AE通过管理后台存在mysql的,那么mysql和es的数据一致性怎么处理?希望老师百忙中解答
作者回复: 1.关于es的使用,的确是要了解了相关检索技术,已经了解了es以后,才能发挥出es的优势。如果你们想走这条路线的话,那需要多花点时间深入了解。 2.你所谓的内存过滤,我的理解就是你们自研系统,在内存中建立索引处理。那么这样的话,你可以结合这个专栏的内容看看如何优化,比如说索引拆分,你们可以指定一个固定分片数,然后在离线环节就拆分好;然后结合全量索引+增量索引的机制,也能保证索引更新时的性能;还有倒排检索加速(参考两篇加餐),应该也是有帮助的。 3.MySQL和es的数据同步问题,其实有许多工具可以做,比如说logstash等。而一致性问题,需要你进行监控和周期性检查,避免有错误。还可以进行周期性完整重建索引的方式,将之前可能已经造成的不一致进行修复。
2020-04-171 - Christmas超大规模的数据量的情况下,感觉按照文档切分,会出现性能问题,分发服务器请求的查询服务器会过多,因为一般es也不建议shard数量很大。不知道业界超大规模额情况下,是按照文档切分的吗?
作者回复: 业界一般都是按文档拆分的,文中和课后习题里,都解释了原因。毕竟对于大部分应用而言,分片数也不会太多。 当然,在极端考虑性能的情况下,是可以考虑关键词拆分的。
2021-03-12