重新自己整理过后的es相关面试题,这里包括八股文和之前面试遇到的问题,后续会持续更新~
- es的类型定义和mysql的映射关系?
- es常用数据类型有哪些?
- es常用方法有哪些?
- es的分词有哪些?
es的类型定义和mysql的映射关系:
es | mysql |
---|---|
索引 Index | 数据库Database |
类型 Type | 表table |
文档document | 数据行row |
字段 Field | column |
es的常用数据类型:
es的常用方法:
例如:PUT /index_name/_doc/doc_id { "field": "value" }
例如:GET /index_name
例如:DELETE /index_name
例如:GET /index_name/_search { "query": { "match": { "field": "value" } } }
例如:POST /index_name/_search {"aggs":{"group_by_field":{"terms":{"field":"field_name"}}}}
例如:GET /index_name/_search { "highlight": { "fields": { "field_name":{}}}}
例如:GET /index_name/_search { "sort": [ { "field_name": { "order": "asc" }}]}
例如:GET /index_name/_search {"from": 0,"size":10,"query":{"match":{"field":"value"}}}
例如:POST /index_name/_doc/doc_id/_update {"doc":{"field":"new_value"}}
例如:DELETE /index_name/_doc/doc_id
es的分词:
- 问题1:有一个字段是”我爱中国“,我想查中国,能查出来么?
答:如果没有分词器,查不出来- 问题2:我有一个自定义的中文词库,能导入么?
答:可以,IK词库支持自定义词库。- 英文是默认空格分词的
集群有多个节点,一个节点正常来说部署一个分片(容灾考虑),当然也可以部署多个分片,每个分片都会有副本分片(当然也可以没有),每个分片是由多个分段组成。每个分片都只为一个索引服务,比如上边的分片12只为索引1服务。
集群:节点通过设置集群名称,在同一网络中发现具有相同集群名称的节点,组成集群。每个集群都有一个 cluster name 作为标识,默认的集群名称为 elasticsearch。如果在同一网络中只有一个节点,则这个节点成为一个单节点集群。
集群状态:
节点:一个 ES 节点就是一个运行的 ES 实例,可以实现数据存储并且搜索的功能。每个节点都有一个唯一的名称作为身份标识,如果没有设置名称,默认使用 UUID 作为名称。最好给每个节点都定义上有意义的名称,在集群中区分出各个节点。
节点类型:
分片(shard):分为主分片和副本分片
副本分片(replica):是分片的一份或多份拷贝,就是副本分片;
replica 的作用主要包括:
注意:对于一个索引,除非重建索引否则不能调整主分片的数目 (number_of_shards),但可以随时调整 replica 的数目 (number_of_replicas)。
倒排索引是一种以词为基础的数据结构,用于将词与包含该词的文档建立映射关系。它的原理是将文档集合中的每个文档进行分词,将每个词与包含该词的文档建立映射关系。具体来说,倒排索引表中的每一项都包括一个属性值(即词)和具有该属性值的各记录的地址(即包含该词的文档列表)。查询时,可以通过倒排索引快速找到包含某个词的文档,从而提高检索效率。倒排索引一般表示为一个关键词和它的频度、位置等信息,好比一本书的目录、标签一般,读者可以根据目录直接找到相关的页面,不必再从书的第一页到最后一页,一页一页的查找。
在Elasticsearch中,Segment是数据存储和检索的基本单位。多个段组成分片,当数据被索引时,它们被分配到不同的Segment中。每个Segment在磁盘上都是一个独立的文件,并且包含了一部分索引的数据。
Segment的主要作用是提高搜索和索引的效率。在执行搜索操作时,Elasticsearch会并行搜索多个Segment,然后将结果合并返回给用户。这种并行搜索的方式能够大大加速搜索过程。而在进行索引操作时,Elasticsearch会根据需要将文档写入到相应的Segment中。这种分段的方式,可以有效地降低内存占用和磁盘的使用,提高索引的效率。
当新的数据被索引时,它们首先被写入到一个新的Segment中。随着时间的推移,旧的Segment可能会被标记为不再使用,并被删除。这个过程是由Elasticsearch自动管理的,用户不需要手动干预。
总之,Segment是Elasticsearch中用于存储和检索数据的基本单位,它通过并行搜索和分段存储的方式来提高搜索和索引的效率。
分段存储:
分段索引:
在Elasticsearch中,分段索引(Segment)是倒排索引的一部分,它是Elasticsearch中最小的存储单元。每个分段都包含了特定范围内的文档数据以及相应的倒排索引信息。分段的存在使得Elasticsearch能够在数据更新、删除、搜索等操作时进行并发处理,从而提高搜索的效率,降低IO的开销,并且还能支持实时搜索等功能。
在底层,Elasticsearch将索引文件拆分为多个子文件,每个子文件就是一个段。每个段本身都是一个倒排索引,并且段具有不变性,一旦索引的数据被写入硬盘,就不可再修改。这种分段存储模式使它在读写时几乎完全避免了锁的出现,大大提升了读写性能。
当文档被索引时,Elasticsearch会自动根据一定的条件触发分段的创建。当索引的文档数量达到一定的阈值时,会触发新的分段的创建。除了自动触发,也可以手动触发分段的创建。通过API可以指定创建新的分段,这在某些情况下是非常有用的,比如在数据导入完成后手动进行一次分段的优化等。
简述概念及区别,可以总的来说,虽然两者都涉及到数据切分,但是
- 分段索引是倒排索引的一部分,是Elasticsearch中最小的存储单元,包含了特定范围内的文档数据以及相应的倒排索引信息,主要关注于倒排索引的组成和存储,用于提高搜索效率、降低IO开销和实现实时搜索的一种机制;
- 分段存储则是将索引数据分成多个独立的段,每个段包含一个索引的文档集合,更关注于整个索引数据的切分和存储方式,这样可以更高效地分配内存和存储空间。
- 什么是索引?
- 索引优化?
- 索引数据多了,如何调优,部署?
- 索引失效的原因?
索引:
Elasticsearch(ES)中的索引是一个逻辑存储空间,用于存储、搜索、分析和查询数据。它类似于关系型数据库中的数据库,可以将数据存放在一台服务器上,也可以分片后存放到多台服务器上。每个索引由一个或多个分片组成,每个分片可以有多个副本。
每个索引包含一个或多个文档,每个文档包含一个或多个字段。这些字段可以是结构化的,也可以是非结构化的。索引的映射定义了文档的结构和字段类型,包括字段名、字段类型、分析器等。
此外,索引还可以进行各种查询和过滤操作,如全文搜索、词条搜索、范围搜索和正则表达式搜索等。通过聚合,可以对文档进行分组和汇总,计算统计信息和计算指标。
索引优化:
索引数据多了,如何调优,部署?
面试官是想考察大数据量的运维能力
索引数据的规划,应在前期做好规划,正所谓“设计先行,编码在后”,这样才能有效的避免突如其来的数据激增导致集群处理能力不足引发的线上客户检索或者其他业务受到影响。
如何调优:
es索引失效的原因?
索引写入:
文档写入:
在写入文档的过程中,Elasticsearch会使用多个线程或进程来并行处理数据写入操作,以提高写入效率。同时,为了防止数据丢失,Elasticsearch会将每次写入的数据同时写入到translog日志中,并提供实时的CRUD操作。此外,为了提高查询性能和容错能力,Elasticsearch会将数据分成多个分片和副本,并使用倒排索引进行索引和搜索操作。
区别:
编译器:编译器用于将字符串分解为术语或标记流。一个简单的编译器可能会将字符串拆分为任何遇到空格或标点的地方。Elasticsearch有许多内置标记器,可用于构建自定义分析器。
分析器:在ElasticSearch中索引数据时,数据由为索引定义的Analyzer在内部进行转换。 分析器由一个 Tokenizer和零个或多个TokenFilter组成。编译器可以在一个或多个CharFilter之前。分析模块允许 您在逻辑名称下注册分析器,然后可以在映射定义或某些API中引用它们。
Elasticsearch附带了许多可以随时使用的预建分析器。或者,您可以组合内置的字符过滤器,编译 器和过滤器器来创建自定义分析器
过滤器:过滤器(Filters)是一种用于在查询中筛选文档的强大工具。过滤器可以根据特定条件来评估文档是否符合搜索查询。这些条件通常应用于字段数据,并根据匹配结果返回符合条件的文档。
在Elasticsearch中,有多种类型的过滤器可供使用,包括:
类型过滤器(Type Filter):根据文档的类型进行过滤,仅返回符合特定类型的文档。
范围过滤器(Range Filter):根据特定范围的字段值进行过滤。
关键字过滤器(Keyword Filter):用于匹配特定文本的过滤器。
布尔过滤器(Boolean Filter):允许根据布尔表达式组合多个过滤条件。
复合过滤器(Composite Filter):将多个过滤条件组合在一起,以实现更复杂的筛选逻辑。
在Elasticsearch中,更新操作可以分为两种情况:更新和替换。
更新(Update):更新操作是对文档的字段进行修改,而不是替换整个文档。当更新一个文档时,Elasticsearch会加载原始文档的源数据,并根据更新请求对字段进行修改。修改后的文档会被保存到倒排索引中,并生成一个新的版本号。
替换(Replace):替换操作是用新的文档替换原始的文档。当替换一个文档时,Elasticsearch会直接将新文档保存到倒排索引中,并生成一个新的版本号。这种操作会比更新操作更加耗时,因为需要将整个文档写入磁盘。
Elasticsearch的更新机制包括以下步骤:
并发更新的冲突处理:
在出现版本冲突的情况下,一般有两种处理方式:
删除操作的执行流程:
合并操作的原理:合并操作是将删除列表中的标识信息应用到倒排索引中的过程。下面是合并操作的原理:
在使用Elasticsearch进行删除操作时,有一些注意事项需要考虑:
- 删除操作并不是直接从磁盘上删除文档,不立即生效,而是将文档标记为已删除状态,所以在搜索时,已删除的文档仍然可以被返回。这是因为Elasticsearch采用了一种称为倒排索引的数据结构来存储文档。倒排索引是一种将文档中的每个词映射到包含该词的文档的数据结构。
- 物理删除:如果需要完全从磁盘上删除文档,可以使用Elasticsearch的物理删除API。物理删除操作会从磁盘上删除文档的索引信息,但需要注意的是,该操作会导致索引变得不可用,需要重新构建索引。
- 自动合并:当执行删除操作时,Elasticsearch会将要删除的文档的标识信息(比如文档的I)添加到一个被称为删除列表(deletelist)的数据结构中,Elasticsearch会自动触发合并操作,将删除列表中的标识信息应用到倒排索引中。但是,如果删除列表的大小较小或者删除操作较少,合并操作可能会较少触发,从而导致已删除的文档占用较多的磁盘空间。可以通过调整合并策略和手动触发合并操作来解决这个问题。
Elasticsearch 提供了乐观并发控制机制来保证读写一致性。具体来说,当文档被更新时,它会检查文档的版本号是否与请求中提供的版本号一致。如果版本号一致,则更新操作成功;否则,更新操作失败,返回文档的当前版本号。这种机制可以防止多个并发操作对同一文档进行修改,从而保证读写一致性。
Elasticsearch 还提供了写一致性级别,包括 quorum、one 和 all。默认情况下,写操作需要在大多数分片可用时才允许执行。这意味着如果大多数分片可用,则更新操作可以成功执行;否则,更新操作将失败。这种机制可以确保在分布式环境下,数据的一致性得到维护。
在读操作方面,Elasticsearch 支持同步和异步读取。默认情况下,读取操作会在主分片和副本分片都完成后才会返回结果。这可以确保读取的数据是最新的。此外,可以通过设置搜索请求参数 _preference 为 primary 来查询主分片,以确保文档是最新版本。
from-size分页:它通过指定起始位置(from)和查询结果数量(size)来获取数据。
在from-size分页中,from参数指定了返回结果集的起始位置,而size参数指定了返回结果集的长度。默认情况下,Elasticsearch中的from-size分页起始位置(from)为0,查询结果数量(size)默认为10。
当需要查询第n页数据时,可以通过计算偏移量来指定起始位置。假设每页显示10条数据,那么第n页的起始位置可以通过(n-1)*10来计算。例如,要查询第2页的数据,可以将from设置为10,size设置为10。
需要注意的是:
- 当查询大量数据时,使用from-size分页可能会对性能产生影响。因为Elasticsearch需要对整个结果集进行排序和过滤,然后再返回指定位置的数据。为了避免性能问题,可以考虑使用search_after分页方式,它基于上一页的最后一条数据来确定下一页的位置,避免了深度分页带来的性能问题。
- 当使用from-size分页时,需要注意返回的数据量不能超过Elasticsearch的限制。默认情况下,Elasticsearch中的最大查询结果数量为10,000条。如果需要查询的数据量超过了这个限制,可以考虑使用scroll API进行滚动查询
search_after分页:search_after分页方式是一种基于上一页的最后一条数据来确定下一页的位置的分页方式。
在search_after分页中,需要设置from参数为0,并使用上一页返回的最后一条数据的sort属性值作为参数传入到search_after中。这样可以确保下一页的数据从上一页的最后一条数据之后开始查询。
需要注意的是,为了使用search_after分页方式,每个文档必须有一个全局唯一值,官方推荐使用_uid作为全局唯一值。另外,在查询时需要根据排序条件设置sort参数,以便正确地找到上一页的最后一条数据。
scroll 深翻页:scroll API使用一个全局深度翻页的操作,首次请求会返回一个scroll_id,使用该scroll_id可以顺序获取下一批次的数据。
scroll API的具体使用步骤如下:
需要注意的是,scroll API只能用于处理大量数据的翻页查询,它可以提高查询性能并避免深度分页带来的性能问题,不能用于实时查询。另外,由于滚动搜索会一直保持一个开启的连接,因此需要确保在使用滚动搜索时不要忘记关闭连接,否则可能会导致资源泄漏。
文件系统缓存(页缓存):当Elasticsearch需要读取某个文档时,它首先会尝试从页缓存中获取该文档的数据块。如果页缓存中不存在该数据块,则会从硬盘中读取该数据块并缓存在页缓存中。这样,在下次需要读取该文档时,可以直接从缓存中获取,避免了磁盘IO操作,提高了查询效率。
需要注意的是,页缓存是操作系统级别的缓存,而不是Elasticsearch自身的缓存机制。因此,页缓存的大小和配置取决于操作系统的设置和硬件资源
分片缓存(Shard request cache):
查询缓存(Filter Cache/Query Cache):用于对一个查询中包含的过滤器执行结果进行缓存。当查询结果被缓存后,后续的相同查询可以直接从缓存中获取结果,无需重新计算。Query Cache对满足某些条件的查询结果进行缓存,例如Term、Range过滤器和特定的聚合结果。Query Cache的主要作用是减少对索引的搜索成本,提高查询效率。
需要注意的是,ES的缓存机制是自动的,不需要用户手动配置。ES会自动根据数据的访问频率和数据量大小等因素来调整缓存的大小和过期时间等参数。同时,为了保持数据的一致性和避免脏读等问题,ES也会对缓存进行同步更新和清理操作。
缓存大小对使用有影响:
缓存大小对Elasticsearch的使用有一定影响。缓存是用于存储经常访问的数据,以便快速响应查询请求,提高查询效率。因此,缓存大小的设置应该根据实际应用的需求和硬件资源进行合理配置。
如果缓存设置得太小,无法容纳足够的数据量,会导致缓存命中率较低,需要频繁地访问磁盘IO,从而影响查询性能。而如果缓存设置得太大,会占用更多的内存资源,可能会导致其他应用或系统资源受到限制。
因此,需要根据实际应用的特点和数据量大小,合理设置缓存大小。可以通过监控Elasticsearch的性能指标,如查询响应时间、缓存命中率等,来调整缓存大小,以达到最佳的性能表现。同时,也需要考虑硬件资源的限制,如可用内存的大小,以确保系统的稳定性和性能。
TermQuery、MatchAllDocsQuery、MatchNoDocsQuery、BooleanQuery、DisjunctionMaxQuery这些查询类型在Elasticsearch中被标记为"not cacheable",意味着它们的查询结果不会被缓存,每次查询都需要重新计算和获取数据。这主要是因为这些查询通常涉及到特定的条件或逻辑,不适合直接从缓存中获取结果。
批量操作是通过_bulk API实现的,它允许你一次性执行多个索引、删除、更新或创建操作。_bulk API的请求体使用JSON格式,其中包含多个操作。每个操作都由一个操作类型和一个请求体组成。
以下是一个_bulk请求的示例语法:
POST /_bulk
{
"operations" : [
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
,
{ "delete" : { "_index" : "test", "_id" : "2" } }
]
}
在上面的示例中,operations数组包含了多个操作。第一个操作是一个index操作,用于将一个文档插入到名为"test"的索引中,文档的ID为"1",字段field1的值为"value1"。第二个操作是一个delete操作,用于删除索引"test"中ID为"2"的文档。
请注意,每个操作都需要单独定义,并在每个操作之间添加一个逗号和一个换行符。此外,还可以定义其他操作,如update和create等;
在Java中使用Elasticsearch Java REST Client进行批量操作的示例代码如下:
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;
import java.util.List;
public class BulkImportDemo {
public static void main(String[] args) throws IOException {
try (RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http")))) {
// 创建bulk请求
BulkRequest bulkRequest = new BulkRequest();
// 添加index操作
IndexRequest indexRequest = new IndexRequest("test");
indexRequest.id("1");
indexRequest.source("{ \"field1\" : \"value1\" }", XContentType.JSON);
bulkRequest.add(indexRequest);
// 添加delete操作
bulkRequest.add(new DeleteRequest("test", "2"));
// 发送bulk请求
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
if (bulkResponse.hasFailures()) {
// 处理失败的操作
List<BulkItemResponse> failures = bulkResponse.getItems();
for (BulkItemResponse failure : failures) {
System.out.println("Failed operation: " + failure.getOpType() + " - " + failure.getFailureMessage());
}
} else {
// 批量导入成功
System.out.println("Bulk import completed successfully.");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
简单地说,就是你检索一个词,匹配出来的文章,网页太多了。比如 1000 个,这些内容再该怎么
呈现,哪些在前面哪些在后面。这需要也有个对匹配度的评分。
是一种基于统计的文本处理方法,用于评估一个词在特定文档中的重要程度。其原理可以概括为:将一个词在文档中出现的次数(Term Frequency,TF)与该词在语料库中出现的次数(Inverse Document Frequency,IDF)相乘,得到该词在该文档中的TF-IDF值。
TF-IDF的具体计算方法如下:
通过TF-IDF算法,可以将文档中的词进行权重化处理,从而为后续的文本分类、聚类和信息检索等任务提供更有价值的特征信息。
Elasticsearch的master节点是集群中的主节点,负责管理集群状态和路由请求。在Elasticsearch中,master选举是通过集群内部的节点之间进行通信和协商来实现的。
步骤:
需要注意的是,Elasticsearch的master选举是自动的,并且不需要手动干预。此外,为了确保集群的稳定性和可用性,建议在生产环境中使用多个master节点,并将它们配置为热备或冷备状态。这样可以减少单点故障的风险,并提高集群的可靠性。
其他节点确定一个节点为主master的方式是通过比较节点的优先级。优先级可以通过多种方式设置,例如通过节点的IP地址或通过配置文件中的优先级值。在选举过程中,具有最高优先级的节点将被选为主master。如果多个节点具有相同的优先级,则根据节点的ID进行比较,ID较小的节点将成为主master。如果ID也相同,则根据时钟时间进行比较,时间较早的节点将成为主master。
Elasticsearch Java REST Client,它是官方的Java客户端,提供了与Elasticsearch进行交互的API。使用该库,可以方便地执行各种API操作,如检索、索引管理、数据更新等。
ELK是三个开源软件的缩写,分别是Elasticsearch、Logstash和Kibana。它们都是开源软件,用于构建实时日志分析系统。
这三个开源软件可以一起使用,形成一个完整的日志分析系统。Logstash可以从各种来源获取数据,经过处理后将其发送给Elasticsearch进行存储和搜索,而Kibana则提供了可视化和查询界面,方便用户查看和分析数据。
ELK系统的主要优势在于其可扩展性、灵活性和可靠性。它可以根据需求进行定制和扩展,支持大量的数据采集、处理和存储,并提供实时的分析和可视化功能。同时,由于这三个软件都是开源的,用户可以根据需要自由选择和修改代码,以满足特定的需求。
总之,ELK是一个强大而灵活的日志分析解决方案,广泛应用于日志管理和数据分析领域。它可以为开发者和企业提供实时的数据分析和可视化工具,帮助其更好地理解应用程序和系统的运行状况。
面试官:想了解应聘者之前公司接触的 ES 使用场景、规模,有没有做过比较大规模的索引设计、规划、调优。实结合自己的实践场景回答即可。
前提四个月导入800w条数据,日增20+w,30列
es 的版本:Elasticsearch 6.x(2019年发布),该版本在性能和稳定性方面进行了改进,同时引入了新的功能和改进,包括Ingest Node, Split and Merge API等;
es有几个节点: 至少3个;
在几个服务器上:3个;
几个分片:5个主分片;
几个副本分片:每个主分片至少一个副本;
内存是多大的:至少16GB,推荐32GB;
索引数据的大小:每天每个索引大小控制在150GB;
数据节点:开始配置3-5个,根据增长情况逐步扩展;
协调节点:查询负载过高,可以设置1-2个;
ES的聚合操作指的是在搜索数据的基础上进行的一种数据分析操作。它可以对搜索结果进行分组、排序、过滤和计算,从而得出具有统计意义的结果。
具体来说,聚合操作可以用于以下方面:
内存参数配置不合理:是否给Elasticsearch实例足够的内存,如果内存足够的话,建议配置30GB每个Elasticsearch数据实例节点。
bulk提交量过大,导致内存被堆满:一次提交的bulk数量不宜过大,实践证明5-10MB左右大小合适。
客户端IP,端口配置问题:因为Elasticsearch的客户端采用的是轮询的方式,所以尽量配置所有节点的IP、端口,或者开启嗅探功能。
写入时指定DOC ID,导致读IO高:写入时指定DOC ID,意味着首先需要判断ID是否重复,如果在大数据量的场景下,可能会需要从磁盘进行一次读操作,从而占用大量的磁盘IO,导致写入速度慢。
bulk队列积压,请求线程被拒绝:大量的bulk队列被等待或者积压,导致线程被拒绝,这时候需要适当降低业务请求的并发量。
热分片问题:单个索引的分片集中分布在某几个机器节点上,导致写入压力无法均匀地分布到各个机器节点上,形成阻塞的问题。
集群不稳定,大量分片迁移和恢复:如果你的集群处于不稳定的状态,比如有大量的分片在做均衡迁移或者恢复,都会占用大量的资源,导致写入资源被占用。
部分实例长时间不断的full gc,导致实例处于假死状态:部分场景下,数据实例处于长时间不断的full gc,但此时并没有完全脱离集群,写入请求仍然往这个节点发送,此时节点已经无法处理了。快速解决办法:重启问题实例。
磁盘IO瓶颈:当磁盘出现IO瓶颈,能怎么办呢,换更好的盘??,或者扩容吧。
查询业务占用大量的资源:高并发的查询或者大数据的查询可能会占用大量的资源,此时需要衡量你的系统侧重点了,实在不行,扩容吧。
索引段合并占用大量的IO资源:索引段合并太频繁同样会占用大量的IO资源,如果不是SSD盘,将索引段合并线程设置为1。
分词器设计不合理:不同的分词对写入影响很大,分词器设计不合理,可能会存在大量的CPU计算和过度分词等问题。