Elasticsearch 面试必备

ELK

E 代表 ElasticSearch,L代表 LogStash,K 代表 Kibana

什么是Elasticsearch

由 Java语言开发基于 Lucene 的 Restful 的分布式实时全文搜索引擎,也可以称作是一种非关系型文档数据库

应用场景:搜索和数据分析

基本概念

  1. index 索引:类似于mysql 中的数据库,用于存放数据
  2. type 类型:在 7.0.0中的API中弃用,并在8.0.0中完全删除
  3. Field 字段:一个document里面有多个field
  4. document 文档:类似于 MySQL 中的一行
  5. shard 分片:es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储
  6. replica 副本:可以在shard故障时提供备用服务,保证数据不丢失
  7. Cluster 集群:包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称)来决定的

近实时(NRT)

从写入数据到数据可以被搜索到有一个小延迟

倒排索引

用于快速查找文档中的词语。它将每个词映射到包含该词的文档列表,以加速搜索。它的优点包括高效的全文搜索、支持复杂的查询和高性能。

mapping

mapping有点类似与RDB中“表结构”的概念,比如字段名称、类型、字段使用的分词器、是否评分、是否创建索引等属性

doc_values

在构建倒排索引的同时,构建了正排索引,从而实现根据指定字段进行排序和聚合的功能

text 和 keyword类型的区别

keyword 类型是不会分词的,直接根据字符串内容建立倒排索引,所以可以通过精确值搜索到

Text 类型在存入 Elasticsearch 的时候,会先分词,然后根据分词后的内容建立倒排索引

query 和 filter 的区别

query:查询操作不仅仅会进行查询,还会计算分值,用于确定相关度;

filter:查询操作仅判断是否满足查询条件,不会计算任何分值,也不会关心返回的排序问题,同时,filter 查询的结果可以被缓存,提高性能。

节点角色

主节点:负责集群本身的管理;比如创建索引;投票节点:只参与主从选举

候选主节点:可以被选举为主节点的节点

协调节点:协调请求的处理过程,一个请求发送到该协调节点会确定数据节点,数据节点执行查询,协调节点将结果集返回

数据节点

master 节点选举

使用一种称为 “Zen Discovery” 的分布式一致性算法来管理集群状态和实现 master 节点选举;过程如下:

  1. 节点发现:集群中的节点通过广播(Multicast)或单播(Unicast)方式互相发现。单播是在 elasticsearch.yml 配置文件中指定其他节点的 IP 和端口。从 Elasticsearch 7.0 开始,广播已被废弃,只支持单播。
  2. 主节点选举:当发现一台或多台节点丢失 master 节点时,集群中的节点会开始主节点选举。每个节点首先会检查自己是否具备成为主节点的资格(主节点资格由配置文件中的 “node.master” 参数决定,该参数默认为 true)。然后,节点将与其他具备主节点资格的节点通信,共同进行选举。
  3. 选举过程:Elasticsearch 使用了一种基于版本号的选举算法。每个节点都有一个集群状态版本号。在选举过程中,具备主节点资格的节点会分享它们的集群状态版本号。具有最高版本号的节点将被选为新的主节点。如果有多个节点具有相同的最高版本号,节点 ID 将作为决定因素,ID 最小的节点将被选为主节点。
  4. 选举结果传播:一旦新的主节点被选举出来,它将通知集群中的其他节点。然后,集群中的所有节点将接受新主节点的指导,并开始执行由主节点分配的集群级任务。

脑裂

当主节点无法工作时,会从备选节点选出一个作为新的主节点。由于网络抖动等原因,主节点未及时响应,集群认为主节点挂了,选举出一个新的主节点,导致出现两个主节点,其他节点不知道听谁调度。

深度分页

深度分页其实就是搜索的深浅度。搜索得太深,就会造成性能问题,会耗费内存和占用cpu。而且es为了性能,他不支持超过一万条数据以上的分页查询。

写入数据流程

1. 文档写入es 的 buffer,同时记录 translog 到 page cache,默认 5 秒刷新到磁盘

2. 文档 buffer 定时刷新到 page cache,默认 1 秒执行一次

包含多个段,每个段包含多个文档

文档写入这里才能被搜索到

每个段都消耗 cpu,内存,文件句柄

3. 刷新磁盘,同时记录一个 commit point

索引和分片

索引有多个分片,每个分片有主从结构

索引机制

倒排索引

写入文档时,根据文档每个字段,使用分词器,将字段值分割为 term;

es 会统计每个 term 频率,构建 term 到文档 id,出现频率,偏移位置的映射(posting list)

FST

类似前缀树,它将前缀和后缀一并压缩

如何保证高可用

核心是分片,通过主从分片,即使主分片崩溃,也基本可用

写入数据时,额外写了 translog,类似 mysql redolog,即使 es 崩溃,也可以恢复数据

高可用方案

限流:

  1. 通过插件机制实现自定义限流(通过 cpu 和内存使用率判断)
  2. 在 es 前增加网关
  3. 在业务测限制查询频率

消息队列消峰:监听 mysql binlog,生成消息到 kafka

保护协调节点:防止遇到大请求情况崩溃,解决办法是设置专门的协调节点

双集群:可以采用消息队列双写 es,查询时判断集群 a 是否有问题,出现问题切换到集群 b

如何优化性能

  1. 优化分页查询:通过 scroll 或者 search after
  2. 批量提交
  3. 优化索引字段:只存必要字段
  4. 增大刷新间隔:index.refresh_interval 为 30
  5. 冷热分离:冷数据放到性能差的服务器
  6. 优化垃圾回收:G1 算法
  7. 优化 swap:将操作系统 vm.swappness 修改为小值;将 es bootstrap.memory_lock=true
  8. 文件描述符
  9. 硬件优化
  10. 分片和副本优化

数据一致性(并发冲突

  1. 使用事务机制
  2. 使用版本控制
  3. 使用分布式锁
展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java