面试 - ElasticSearch面试题
文章目录
如果想系统性的学习ES,可以看我的这个专栏
一:什么是ES


和传统关系型数据库的名词对应关系

二:ELK和FELK
基本ELK = es + logstash + kabana
logstach => 对日志进行收集和过滤
es => 日志信息的存储和检索
kabana => 可视化界面和统计

FELK = filebeat + es + logstash + kabana
filebeat => 数据采集器(从filebeat的指定中指定日志采集的数据)

beat介绍 - 数据的采集,指定要采集那些日志中的数据
Beats是一款轻量级的数据采集器,用Go语言进行编写,并且集合了多种单一用途的数据采集
这些采集器安装之后可以用作轻量级的代理服务器,从成千上万台机器向Logstash中进行转换和解析
Beats中集合的每款开源采集器都是以libbeat[用户转发数据的通用库]为基石的,用户需要监控某个专用协议的时候,可以自主构建采集器。
logstash介绍 - 对采集过来的数据进行转换,过滤等操作,变成符合ES格式要求的
Logstash是一个动态的数据收集管道,拥有可以扩展的插件生态系统,支持从不同的来源收集数据和转换数据,并将转换后的数据发送到不同的存储库中,
Logstach能够和ES强力系统工作,13年LogStash被Elastic公司收购
Logstash具有如下的特点:
- 实时性,可以实时的解析数据并对数据进行过滤处理
- 可扩展性:具有200个插件,可以接受的数据来源多种多样
- 可靠性和安全性:Logstash会通过持久化队列来保证智商将数据送达一次,同时对数据进行传输加密
- 实时监控能力,对可以接受的数的数据源进行监控,一旦数据源产生新的数据就会立刻进行传输
ES介绍 - 日志信息的存储和检索
ES可以对数据进行全文检索,分析和存储,是基于JSON的分布式数据搜索和数据分析引擎,是专门为实现架构的水平可扩展性、高可靠性和管理便捷性而设计的产品
ES的主要实现分成下面几个步骤:
- 用户将数据提交到ES数据库中
- 通过分词控制器对对应的语句进行分析
- 通过分词结果和权重一起存储,当用户检索数据的时候,根据权重和对搜索结果进行排名和打分【分数越高,匹配度就越高】,最终将结果呈现给用户
Kibana介绍 - 可视化展示和操作界面
Kibana可以实现数据可视化,他的作用是在ES中对数据进行管理和展示,能够通过图表的形式将数据呈现给用户
Kibana具有高可扩展的用户界面,能够全方位的管理ES中的数据,Kibana最早的时候是基于Logstash的创建的工具,具有如下的特点:
- Kibana可以提供各种可视化图表,只需要简单的配置就可以了
- Kibana可以通过机器学习技术对异常的情况进行检测,以提前发现可疑的问题
一般企业级都会配合上Kakfa

🎉 对于具体的部署,可以看我的这篇文章或者在网上搜索部署
三:Text和Keyword的区别

text类型
当一个字段是要被全文搜索的,例如Email,那么这个字段应该使用text类型
设置text类型之后,字段内容会被分析,在生成倒排索引之前,会被分析器分成一个一个词项,text字段类型的字段不用于排序,很少用于聚合
对于text字段由如下注意事项:
- 使用于全文检索,例如match查询
- 文本字段会被分词
- 默认情况下,会创建倒排索引
- 自动映射器会为Text类型创建KeyWord字段
keyword类型
KeyWord类型适用于不分词的字段,如姓名,ID,数字等
如果数字类型不用范围查找,那么keyword的性能要高于数值类型
当使用keyword类型进行查询的时候,其字段值会被认为是一个整体,并保留字段值的原始属性
常用于过滤,排序,聚合
GET test_index/_search
{
"query": {
"match": {
"title.keyword": "测试一下"
}
}
}
对于keyword类型,有如下注意事项:
- 不会对文本分词,会保留字段的原有属性,包括大小写等等
- 仅仅是字段类型,不会对搜索词产生任何的影响
- 一般用于需要精确查找的字段,或者聚合排序的字段
- 通常和term一起使用【DSL】
ignore_above参数代表其切断长度,默认是256,如果超过长度,字段值会忽略,而不是截断
四:全文检索和倒排索引

倒排索引的物理结构和逻辑结构(黑色是物理结构,黄色是逻辑结构)

五:B+树为什么不适合做全文索引

通过上图可知,b+树相对来说不能作为全文索引有三个原因:
- IO次数过多,因为索引字段比较长,会使得树的高度比较高,IO次数就会较多
- 性能无法确保,且容易索引失效
- 精度较低,无法和其他的属性产生关联
六:ES是如何优化写入流程的

- 写入内存buffer, 同时写入到os cache中
- 内存buffer中的数据,每过1s, refresh到os cache中
- 在os cache的数据此时能被检索到,内存buffer中的数据将会被清空
- os cache中的数据每过5秒,写入translog中(类似于mysql的bin log)所以此时如果宕机,ES最多会有5s的数据丢失
- os cache会通过fsync将内容刷入到segment中
- 清空translog, 重启一个

七:ES性能问题
分几个方向说几个点:
硬件配置优化 包括三个因素:CPU、内存和 IO。
- CPU:
- 大多数 Elasticsearch 部署往往对 CPU 要求不高;
- CPUs 和更多的核数之间选择,选择更多的核数更好。
- 多个内核提供的额外并发远胜过稍微快一点点的时钟频率。
- 内存:
- 配置: 由于 ES 构建基于 lucene,而 lucene 设计强大之处在于 lucene 能够很好的利用操作系统内存来缓存索引数据,以提供快速的查询性能。lucene 的索引文件 segements 是存储在单文件中的,并且不可变,对于 OS 来说,能够很友好地将索引文件保持在 cache 中,以便快速访问;因此,我们很有必要将一半的物理内存留给 lucene;另一半的物理内存留给 ES(JVM heap)。
- 禁止 swap,一旦允许内存与磁盘的交换,会引起致命的性能问题。可以通过在
elasticsearch.yml中bootstrap.memory_lock: true,以保持 JVM 锁定内存,保证 ES 的性能。 - 垃圾回收器: G1 GC,运行效果良好,对Heap大对象优化尤为明显。
- 磁盘:
- 在经济压力能承受的范围下,尽量使用固态硬盘(SSD)
八:分片和副本
在 Elasticsearch 中,索引是文档集合的基础,由多个分片(Shard)组成。分片是数据分布的基本单位,每个分片本身就是一个完整的索引。索引中的文档被散列到各个分片中,这种散列过程允许 Elasticsearch 分布式地存储大量数据并执行并行操作,从而提高性能和吞吐量
主分片
在创建索引时定义的分片数量,这决定了索引能存储的最大数据量和处理的能力。每个主分片可以存储和索引文档,主分片的数量在索引创建时设定后不可更改
- 数据写入时,文档根据其 ID 经过散列(hashing)函数分配到具体的主分片。
- 数据查询时,查询被发送到所有相关的分片(可能是主分片或副本分片),然后结果被汇聚和返回。
副本
是主分片的拷贝,可用于提高系统的高可用性和读取操作的伸缩性。副本数量可以动态调整
- 副本分片可以处理读请求(比如搜索和检索),从而分担主分片的压力。
- 在主分片不可用时,副本分片可以提供数据并维持应用的可用性。
- 添加副本可以提高故障转移能力,如果节点或分片失败,其它副本可以接管这部分工作。

分片和副本存在的意义
- 水平扩展:增加节点可以重新分配和平衡分片,轻松实现水平扩展。
- 可用性和冗余:副本提供了数据的备份,即使部分节点或硬件故障也不会丢失数据。
- 负载均衡:搜索和读取请求可以在所有副本分片之间进行负载均衡。
- 并行处理:更新、搜索可以并行在多个分片上执行,提高了大数据集上的操作速度。
注意事项
- 分片一旦创建,不可更改其数量(除非重新索引)。
- 副本数量则可以根据读取性能的需求和系统的高可用性需求动态调整。
正确的管理和配置分片和副本策略对于 Elasticsearch 集群的高效运作至关重要。通过优化分片数量、副本策略以及集群资源配置,可以确保 Elasticsearch 集群的性能和稳定性。
九:常用操作说明
1:创建索引操作(创建数据库表)
PUT /my_index // 注意使用的是put, 语法是put /索引名称 {setting, mapping}
{
"settings": {
"number_of_shards": 3, // 分片数
"number_of_replicas": 2 // 副本数
},
"mappings": {
"properties": {
"field1": { "type": "text" },
"field2": { "type": "integer" }
// 其他字段和字段类型...
}
}
}
2:增删改查操作
POST /movies/_search // 查询操作是POST请求,POST /索引名称/_search
{
"query": {
"match_all": {} // 这块比较多内容
}
}
POST /movies/_doc/ // 插入也是POST请求 POST /索引名称/_doc
{
"title": "AAAAAAAAAAAAAAAAAAAA",
"year": "2020",
"type": "剧情",
"star": 5.2,
"director": "BBBBB" // 要插入的JSON数据
}
# DELETE /库名/_doc/文档id , 根据文档id进行删除
DELETE /movies/_doc/1
# 根据查询语句删除
POST /my-index/_delete_by_query
{
"query": { # 删除条件
"match": {
"user.id": "elkbee"
}
}
}
#删除所有数据
POST /my-index/_delete_by_query
{
"query": {
"match_all": {}
}
}
对于数据的更新,有三种方式:
put - 覆盖式更新 - 有则更新,没有则创建

POST方式的更新
POST /库名/_doc/文档id # 这也是一种覆盖式方式, 结果和 PUT 是一样的. 同样的, post也可以新增数据.
POST /库名/_update/文档id # 非覆盖式方式, 他只有修改的功能, 没有新增文档的功能

方式三:指定条件的更新
POST /index_name/_update_by_query
{
"query": {
"term": {
"is_stopped": true // 设置更新条件
}
},
"script": {
"lang": "painless",
"source": "ctx._source.is_stopped=false" // 设置更新内容
}
}
3:聚合操作

// 桶聚合的结构
"aggs" : {
"聚合结果的名称" : {
"单个桶的类型" : {
"field" : "字段"
}
}
}
GET /test-agg-cars/_search
{
"size" : 0, // 指定返回的hits的个数,0个就是不返回hits的条件
// 聚合操作
"aggs" : {
"popular_colors" : { // 第一个聚合,聚合名称是popular_colors
"terms" : { // 第一个聚合的类型,是terms,要求下面是terms匹配
"field" : "color.keyword" // 聚合条件,group by(color.keyword)
}
},
"make_by" : { // 第二个聚合,聚合名称是make_by
"terms" : {
"field" : "make.keyword" // 聚合条件,group by(make.keyword)
}
}
}
}


十:脑裂问题
脑裂问题发生在集群系统中,当节点之间的网络连接出现故障(但节点本身仍在运行),导致集群被分割成两个或多个部分,每个部分都认为其他部分已经宕机,从而各自形成独立的集群继续运行。
脑裂成因
- 网络问题
集群间的网络延迟导致一些节点访问不到 master,认为 master 挂掉了从而选举出新的 master,并对 master 上的分片和副本标红,分配新的主分片
- 节点负载
主节点的角色既为 master 又为 data,访问量较大时可能会导致 ES 停止响应造成大面积延迟
此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点
- 内存回收
data 节点上的 ES 进程占用的内存较大,引发 JVM 的大规模内存回收,造成 ES 进程失去响应
解决方案
- 减少误判
调大节点状态的相应时间,防止因为延迟而造成的误判
修改discovery.zen.ping_timeout (默认为3s,可以调整为6s等)
- 选举触发
节点个数为奇数,防止选举时多个为master
- 角色分离
即 master 节点与 data 节点分离,限制角色
主节点配置为:node.master: true node.data: false
从节点配置为:node.master: false node.data: true
十一:文档路由介绍
Elasticsearch 中的文档路由(Document Routing)是指定义文档存储在哪个分片上的过程。
在 Elasticsearch 中,索引可以被分为多个分片(shards),而默认情况下,文档被存储到分片的决策是由文档的 _id 和分片的数量计算得出的。
路由是用来改变默认行为,并且可以控制特定文档应该被路由(存储)到哪一个分片上。
为什么需要文档路由?
在某些场景中,文档路由可以提高效率:
-
数据局部性:将相关联的文档存放在同一个分片中,可以提升部分查询的性能,因为相关的数据都在一个地方,从而减少跨分片的通信开销。
-
高度可用的写入模式:当你知道特定类型的文档非常频繁地被查询或更新,把这些文档存放在同一个分片可能可以提高性能。
-
避免大型文档集中:有时候文档大小差异很大,可以通过路由保证分片之间的负载均衡。
如何实现文档路由
当你索引、搜索、更新、删除文档时可以指定路由参数,定义文档应该去哪个分片。
PUT /my-index/_doc/my-id?routing=user123
{
"name": "John",
"age": 30,
"level": "senior"
}
// 当你需要根据特定逻辑(比如,用户的 ID 段)进行搜索时,也可以提供路由参数
GET /my-index/_search?routing=user123,user124
{
"query": {
"match": {
"name": "John"
}
}
}
文档路由的策略
选择文档路由策略时,需要平衡副本的分布和性能。一个好的路由策略既可以减少资源使用又能提高查询效率。但同时,错误的路由策略可能导致分片数据不均衡(Hotspot),降低集群的总体性能。
在生产中使用文档路由时需要谨慎,仔细评估路由策略对集群状态、数据分布和查询性能的影响。文档路由的最佳实践应该在详尽的测试后决定,并持续监控分片的大小和负载情况。
十二:ES性能监控
监控ES的集群
使用 Elasticsearch 原生 API:
- _cluster/health 和 _nodes/stats 提供集群健康和每个节点的统计信息。
- _cat API 提供一种直观的方式来获取包括分片分配、内存使用和集群节点等信息。
集成监控工具:
-
使用如 Elastic Stack 的 Kibana 中的监控插件,或 Grafana 与 Prometheus 等开源或商业监控解决方案。
-
使用 APM 工具收集和分析应用程序性能数据。
实时性能监控:
- 配置阈值和开启报警规则,当出现诸如磁盘空间不足、CPU 使用率过高或 JVM 内存压力增大等情况时及时告警。
调整ES的集群性能
硬件资源调整:
-
增加硬件资源,尤其是内存和 CPU,以提升节点性能。
-
优化磁盘使用,使用 SSD 可显著改善 I/O 性能。
JVM 配置:
-
配置合适的 JVM 堆内存,一般建议设置为物理内存的一半,且不超过 32GB。
-
定期进行 JVM 堆调优和垃圾回收策略的评估。
索引策略优化:
-
适当设置索引分片(shards)和副本(replicas)以平衡写入性能和容错需求。
-
定期执行索引维护,如优化和删除不再需要的索引。
查询优化:
-
优化搜索查询语句,避免昂贵的查询操作,如深度分页和仅用于过滤的高成本聚合。
-
使用缓存策略来避免重复执行的查询。
网络优化:
- 优化集群节点之间的网络连接,确保低延迟和高可用带宽。
- 保持数据本地化减少跨数据中心的通信。
批量处理和并行处理:
- 使用批量 API 进行高效的数据导入。
- 利用并行查询优化搜索性能。
数据建模:
- 根据你的使用场景和数据访问模式设计数据模型。
- 避免巨型文档(large documents)和巨型索引(large indices),它们可能导致性能下降。
写入性能:
- 关闭或调整 refresh 和 flush 设置来平衡索引更新与搜索可见性的需求。
- 合理配置索引缓冲区(indexing buffer)。
安全机制:
- 保证使用高效的安全协议和加密措施,避免影响性能。
十三:ES故障排查思路
监控集群健康
通过 Kibana、Elasticsearch-head、Cerebro 等工具或直接使用命令行来执行。
GET /_cluster/health
监控健康状态和关键指标,如节点数量、分片状态、未分配分片等。
检查集群日志
查看 Elasticsearch 的日志文件以获取故障的详细信息。
Elasticsearch 通常会记录有关异常和内部错误的详细信息。
日志文件一般位于 <Elasticsearch_Home>/logs/ 目录下。
确定故障原因
找到造成集群故障的根本原因是故障处理的重要组成部分。常见的原因包括:
- 硬件故障
- 网络问题
- 软件错误
- 配置错误
- 资源不足,如内存、CPU 负载过高或磁盘空间不足
解决硬件和网络问题
确认服务器硬件是否运行正常,并检查网络连接是否稳定。这可能涉及到影响集群节点通信的交换机、路由器和防火墙等。
恢复失败的节点
集群中的节点如果失败,尝试重启节点,并确认节点重新加入集群后恢复正常。
调整集群配置
根据需要调整 Elasticsearch 的配置。如调整 heap 大小、增加数据节点来提高处理能力或调整分片和副本的数量等。
分配未分配的分片
如果有未分配的分片,使用 _cluster/reroute API 来手动重新分配分片。
POST /_cluster/reroute
{
"commands" : [
{
"allocate_stale_primary" : {
"index" : "index_name",
"shard" : 0,
"node" : "node_name",
"accept_data_loss" : true
}
}
]
}
防止数据丢失
如果集群有数据丢失的风险,采取措施避免重要数据丢失。确保从备份中恢复数据或使用快照。
处理软件问题
如果问题是由 Elasticsearch 软件的错误或 Bug 导致的,考虑升级到修复该问题的较新版本,或寻求 Elastic 社区支持。
扩展资源
解决资源不足的问题,可以是添加更多服务器、增加硬盘容量或其他计算资源。
运维和自动化
自动化运维任务,如定期备份、自动健康检查,以便快速响应未来的问题。
处理集群故障需要了解 Elasticsearch 的内部工作机制和集群管理知识。文档和社区论坛是处理集群问题的宝贵资源。
十四:如何实现水平扩展
Elasticsearch 的设计目的之一就是为了水平扩展,也就是说通过添加更多节点来扩大集群的容量和增强性能
自动分片
- Elasticsearch 的索引被分为多个分片(shards),它们可以分布在不同的节点中。
- 分片分为主分片(primary shards)和副本分片(replica shards)。主分片负责索引文档,副本分片提供冗余和读取性能。
动态添加节点
- 向集群中添加新节点时,Elasticsearch 会自动进行数据重新平衡(rebalancing),将分片从旧节点移动到新节点。
- 重新平衡是为了保持集群中所有节点的数据分布大致均匀。
扩展读写性能
- 水平扩展可以增强集群的读写吞吐量。
- 写入操作可以在多个主分片上并行进行。
- 读取操作可以在主分片和副本分片上分散执行,从而提升并发读取性能。
使用分片策略
- 适当设置索引的分片数量对于水平扩展至关重要。
- 在创建索引时就需要决定主分片的数量,因为后续改变这个数量需要重新索引。
分区(Routing)
- 自定义路由策略可确保相关的文档基于某个值(如用户 ID)存储在同一分片中,这可能有助于一些特定的查询性能。
高可用副本(Replicas)
- 增加副本分片的数量可以为读请求提供更大的吞吐量和更高的可用性。
监控和调节集群
- 使用诸如 Elasticsearch 集群 API、Kibana 监控插件和其他监控工具来监测集群状态和性能指标。
- 根据监控结果动态调整副本数量,优化分片分布等。
处理热点(Hotspots)
- 避免某个特定节点或某些分片过载,确保集群的负荷均衡。
硬件和资源管理
- 水平扩展时考虑加入的新节点的硬件规格,保持适当的硬件水准和资源配比。
十五:ES搜索模板有哪些
Elasticsearch 中的搜索模板(Search Templates)提供了一种机制,允许开发者在查询中使用可配置的、可重用的模板,而不是硬编码所有查询的完整定义。搜索模板的主要作用如下:

先创建一个模板
POST _scripts/my_template
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"{{field}}": "{{value}}"
}
}
}
}
}
然后使用模板
GET /your_index/_search/template
{
"id": "my_template",
"params": {
"field": "title",
"value": "Elasticsearch"
}
}
十六:ES的管道是什么,如何使用
在 Elasticsearch 中,管道(pipeline)是指一系列用于在文档被索引之前对其进行处理的处理器(processors)。管道使得用户可以定义一个或多个处理器,这些处理器对文档执行各种中间转换,如提取字段、重命名字段、删除字段、转换字段格式等。Elasticsearch 中的管道类似于数据预处理或摄取管道(ingest pipeline)
1️⃣ 清洗类管道
PUT _ingest/pipeline/my_pipeline
{
"description" : "My ingest pipeline",
"processors" : [
{
"set" : {
"field" : "new_field",
"value" : "value_of_new_field"
}
},
{
"rename" : {
"field" : "old_field",
"target_field" : "new_field_name",
"ignore_missing" : true
}
}
// 更多处理器...
]
}
2️⃣ 更新类管道
PUT _ingest/pipeline/my_pipeline
{
"description" : "My updated ingest pipeline",
"processors" : [
{
"set" : {
"field" : "another_new_field",
"value" : "another_value_of_new_field"
}
}
// 更改后的处理器列表...
]
}
3️⃣ 模拟类管道
为了验证管道处理器配置的正确性,可以模拟处理文档,而不实际索引它们:
POST _ingest/pipeline/my_pipeline/_simulate
{
"docs": [
{
"_source": {
"old_field": "old value"
}
}
]
}
4️⃣ 删除类管道
DELETE _ingest/pipeline/my_pipeline
5️⃣ 使用管道
在索引文档时,可使用 pipeline 参数指定刚创建的管道:
PUT my-index/_doc/my-id?pipeline=my_pipeline
{
"message" : "some message",
"old_field" : "old value"
}
十七:X-Pack插件
X-Pack 是一个由 Elastic 公司开发的扩展套件,用于为 Elasticsearch 和 Kibana 提供安全性、监控、报告、机器学习等企业级功能。
X-Pack 是 Elastic Stack 的重要组成部分,提供了许多内置功能,从而增强了 Elastic Stack 在日常运维和数据分析中的能力。
虽然 X-Pack 是一个商业产品,但它提供基础版本,其中包括了一些免费的功能。以下是 X-Pack 提供的主要功能和特征:
安全(Security)
用户验证:提供了用于保护 Elasticsearch 集群的基本认证,如内置用户和密码。
角色基于访问控制(Role-Based Access Control, RBAC):支持基于角色的访问控制,可以管理用户对数据和集群资源的访问。
加密:支持在节点之间的通信加密(TLS/SSL),保障数据在传输过程中的安全。
监控(Monitoring)
数据收集:收集有关 Elasticsearch 集群的性能和健康数据。
可视化:使用 Kibana 查看和分析监控数据,以帮助及时发现潜在问题。
报告(Reporting)
报告生成:在 Kibana 中创建可视化报告,并将其导出为 PDF、CSV 等格式。
机器学习(Machine Learning)
异常检测:使用机器学习算法自动模型化 Elasticsearch 数据,并识别异常模式。
预测性分析:在时间序列数据上建立机器学习作业,预测未来可能的趋势。
图形和探索(Graph & Discovery)
图探索:使用 X-Pack 的图探索功能从复杂的数据关系中发现隐藏的模式和连接。
监管遵从(Compliance)
数据保留政策:通过索引卷曲和数据保留,帮助组织符合行业相关的数据保留要求。
通知和警报(Alerting)
使用 Watcher:定义自动触发动作的条件,当条件满足时发送通知或执行特定操作。
SQL(SQL and JDBC)
使用 SQL 语句:对 Elasticsearch 索引执行 SQL 查询,并编程地通过 JDBC 接口访问 Elasticsearch 查询结果。
键管理(Key Management)
密钥轮换和管理:管理加密密钥和证书,确保Elasticsearch 易于维护,同时提供高级安全性。
随着 Elasticsearch 开发社群的发展,Elastic 公司为部分 X-Pack 功能引入了更开放的许可证或将它们合并到了基本功能中。在某些场合中,X-Pack 中开源的功能也被社区项目替代或补充,例如开源的 Open Distro for Elasticsearch 提供了许多相似的功能。
使用 X-Pack 可以使得运维 Elasticsearch 和应用 Elastic Stack 的机构更容易遵守安全标准,同时获得企业级的数据分析和搜索体验。
十八:ES和MySQL的同步方案

送到RocketMQ之后,就可以通过读取RocketMQ中的数据完成数据的同步
1221

被折叠的 条评论
为什么被折叠?



