Elasticsearch,分布式搜索引擎

有些人的服务器内存太小,可能会部署不了,但是嘛,你可以不做,不过你得懂大概怎么弄。

ES一般不会问的很难,因为说实话,大部份人确实只会用基本的ES,所以你最少要掌握:ES是什么?为啥她可以高效搜索?你自己在项目中是怎么配置的?

这三个问题搞定就完成了最基本的了。

然后下面我也让面试官给总结了一些常见可能会问的,可能有点难,大家有个大致的印象也行。

ElasticSearch全局搜索

参考资料

搜索功能是如何实现的?

首先是在springboot中添加spring data es的依赖,并且在配置文件中对es的相关信息进行配置,例如集群名称,节点地址等。然后在帖子类和评论类里添加es的注解@Document(索引名,类型等参数)。之后创建对应的 Repository 接口,用于与 Elasticsearch 进行交互 。在帖子评论发布的时候,将数据通过kafka异步发送到kafka的topic上,并创建kafka的消息监听器@kafkaListener 然后将收到的消息存入es当中。 通过 Elasticsearch 的查询 DSL 实现关键词搜索功能 。

ElasticSearch做全局搜索的优势是什么?为啥不选择用MySQL?

全局搜索的优势:首先es是分布式搜索引擎,能够轻松的在多节点之间分片复制数据,吞吐量和可用性都很高。其次它支持实时搜索,可以快速对数据进行索引查询。并且它基于lucene实现了强大的全文搜索能力,还有丰富的查询DSL,可以满足复杂的搜索情况。最后他们的社区建设很好,插件和扩展也十分丰富。

为什么不用Mysql:mysql虽然支持全文搜索,但是无论是功能上还是性能上都很差。在处理复杂大规模数据查询的情况下,性能很低。并且它更适合结构化内容,但是搜索引擎的查询内容往往都不符合结构化的要求。此外,在分布式的扩展性,实时性上,es都完爆mysql。MySQL 作为关系型数据库,更适合事务处理和结构化数据管理,无法在全文检索和复杂查询场景中提供同样的性能和功能

请描述一下ElasticSearch的基本架构和工作原理

先来聊聊lucene;lucene对es影响最大的一点就是倒排索引

倒排索引是为每个单词建立一个记录,列出包含该单词的所有文档。这样在搜索时,只需查找单词对应的记录即可快速定位包含该单词的所有文档。从而实现高性能全文搜索。此外,lucene底层还实现了复杂的评分与排序算法,丰富的分词器和分析器。缺点也很明显,太难用了。直接使用它需要大量的配置工作。而es则实现了更高层次的抽象功能,使得用户可以很方便的实现复杂的搜索分析需求,易用性更强。比如通过简单直观的restful api,通过http请求进行操作,支持复杂的DSL查询语句。

再来看它的基本架构

首先是集群,集群是由一个或多个节点组成的集合,集群中的节点协同工作。

其次是节点,节点就是一个运行的es实例,可以是主节点,数据节点,协调节点之类。

然后是索引,可以看作是一个数据库,有多个类型相似的文档。

类型相当于是关系型数据库里的表,在我用的版本已经被弃用,但是postman里面还是有它的影子。

最后是字段,字段相当于是列,也就是每个字段对应的值。

最后来看工作原理,当我们把数据发送给es时,这些数据会被封存在一个名为索引的结构中,索引中包括多个文档,每个文档都是json格式的数据对象。文档存储在索引的分片里,每一个分片是一个独立的llucene索引。es自动将文档分配到不同的分片里,并配置分片的副本以提高可用性。除此以外,我们前面有提过的倒排索引将文档中的词项映射到文本的id中,也就是这些词出现在哪些文档中。这样就可以实现快速的查询。

数据写入流程如下:客户端发送http请求,将文档写入es中,然后es集群根据索引的路由算法,将请求路由到负责处理该文档的主分片中,随后复制到所有副本分片中。

数据查询流程如下:客户端发送一个http请求,包含查询的dsl,es的协调节点解析查询dsl,将查询请求发给对应的分片,然后分片搜索,将匹配的结果返回给协调分片。协调分片进行结果的合并,并返回结果给客户端。

集群管理:es集群由多个节点构成,每个节点都是独立的es实例。主节点负责管理集群的状态,包括索引的创建删除更新等操作。索引被切割成多个分片,每个分片在不同的节点上,用于提高可用性。主节点检测到节点故障时,要分配故障节点的分片给其他的可用节点。

你是如何设计和创建索引的?索引结构是怎样的?

索引主要是为了搜索帖子和评论的关键词,所以对应的字段就是标题,内容,作者id,时间戳等等。

然后要定义映射,标题和内容全文搜索需要文本类型和标准分析器。时间戳则是使用日期类型并定义日期格式。

分片和副本的数量不用太多,分片数量设置为3,副本设置为1

最后写出来的代码里,title和context的analyzer是standard。作者可以用关键词,时间戳我们定义了format。

数据是如何从数据库同步到ElasticSearch的?使用了哪些工具或技术?

这里可以先使用CDC工具例如Debezium来捕获数据变更,将变更记录转化为消息,发送给kafka的topic,kafka消费者读取这个数据变更事件,转化为es可以接受的格式,发送给es。

ElasticSearch如何进行全文检索?你在项目中是如何配置的?

主要大概有三个方法,

首先是match query,单个字段中进行全文的检索。

然后是Multi match query,在多个字段中进行全文检索。

最后是bool query,进行复杂布尔查询,可以组合多种查询条件。

配置的大体过程就是先安装es,然后springboot中导入依赖,在配置文件里配置es,实体类里添加es的注释document,最后创建一个接口继承es repository,利用编写的服务类中dsl进行查询即可。

搜索结果的排序是如何实现的?有哪些排序规则?

在ElasticSearch中,搜索结果的排序主要依赖于相关性评分。这一评分系统默认使用BM25算法,这是一种基于信息检索的评分算法,它综合了几个重要因素来决定结果的相关性。

BM25算法考虑了词频(文档中查询词的出现次数)、文档长度(文档的总词数)和逆文档频率(词在所有文档中的稀有程度)等因素。这些因素帮助算法计算每个文档的相关性得分,从而对搜索结果进行排序。简单来说,它帮助确定哪些文档最相关,以便将最匹配的结果排在最前面。

除了基于BM25的相关性评分,ElasticSearch还允许按其他字段进行排序。例如,你可以按文档的发布时间排序,确保最新的内容显示在最前面。还可以指定多个排序条件,比如先按相关性评分排序,再按发布时间排序,这种多重排序条件能更精确地满足用户的搜索需求。

此外,ElasticSearch也支持自定义排序规则,你可以通过编写自己的评分脚本来实现特定的排序需求。这样可以根据业务逻辑或特定的需求调整排序方式,实现更加灵活的结果排序。

如何实现高效的分页查询?

小数据量的情况下,使用基于from和size参数的查询即可。指定从第几条数据开始,返回多少条记录。但是大量数据时由于跳过的数据太多,性能会下降。

search-after适用于深度分页,避免大数据量分页时的性能问题。它要求排序字段唯一,查询结果稳定。第一次查询设置排序字段,第二次采用第一次查询最后一个文档的排序值进行下次查询,避免大数据量的性能瓶颈。

scroll适合对大量数据滚动处理的情况。初始化滚动时间和查询参数,获取一个scroll id,之后的查询会利用scroll id进行逐步的读取数据。就相当于是一个书签,能够定位上下文,从上一次的地方继续读,避免一次性加载太多,内存的溢出或性能问题。

随着数据量的增加,ElasticSearch的性能是否会受到影响?你是如何应对的?

如果有钱,首选肯定是硬件上选择更好的硬件配置,增加内存,使用更快的存储设备。

没钱就从数据建模角度先优化。首先设置合理的索引分片数量,过多会导致资源消耗与管理困难,过少会导致分布不均,查询并行度低。其次是查询优化,例如过滤查询代替评分查询,不涉及计算过程以提高性能。采用前缀查询,只返回必要的字段等。最后是索引优化,定期进行段合并,删除旧数据。

没尝试过但可去做的就是缓存优化,例如查询先做缓存,热点查询数据预热等。

发表评论

后才能评论