ES倒排索引实现? ES 索引文档过程?ES并发下读写一致?

ES倒排索引实现, ES 索引文档过程,ES并发下读写一致

一、Elasticsearch的基本概念

  1. 索引(Index)
    索引是Elasticsearch中存储数据的地方,可以把它理解为一个优化过的、快速查询的大型文档集合。
    索引类似于关系型数据库中的"数据库"或"表"的概念,但它是面向文档的,且每个字段都可以被索引和搜索。
    索引由名称(必须为全小写字符)标识,并通过此名称进行文档的创建、搜索、更新及删除操作。
  2. 文档(Document)
    文档是Elasticsearch中的最小单位,是索引中的一条数据。
    文档以JSON格式存储,包含多个字段,每个字段的类型由映射(Mapping)定义。
    文档的字段类型可以是文本、数值、日期等,也可以是复杂类型,如嵌套文档或数组。
  3. 映射(Mapping)
    映射定义了索引中文档的结构,包括字段的名称、类型和其他相关设置。
    类似于关系型数据库中的模式(Schema),但Elasticsearch支持动态映射,即可以在插入新字段时自动创建映射
  4. 分片(Shard)
    分片是Elasticsearch分布式架构的基础,每个索引都可以被分成多个主分片(Primary Shard)和副本分片(Replica Shard)。
    主分片负责数据的存储和索引类似于数据库中的分库分表,而副本分片则提供数据的冗余存储和负载均衡类似数据库中的主从节点。
    分片使得Elasticsearch能够横向扩展至数以百计的服务器,处理PB级的数据
  5. 节点(Node)
    节点是Elasticsearch集群中的一个实例,它可以是主节点(Master Node)、数据节点(Data Node)或客户端节点(Client Node)。
    主节点负责集群的元数据存储和协调,数据节点负责数据的存储和检索,而客户端节点则提供RESTful API接口供外部访问

二、Elasticsearch的工作原理简述

  1. 索引过程:

    当向Elasticsearch中存入文档时,它会自动对文档的内容进行索引。

    索引过程包括分词和倒排索引,帮助系统快速找到与查询匹配的文档。

  2. 查询过程:

    查询请求会首先被发送到客户端节点或数据节点。

    节点会根据查询条件将请求路由到包含相关数据的分片上。

    分片会执行查询并返回结果给节点,节点再将结果汇总后返回给客户端。

三、Elasticsearch的应用场景

  1. 全文搜索:
    适用于需要全文检索的应用场景,如搜索引擎、文档管理系统等。
  2. 日志分析:
    适用于需要实时分析日志数据的应用场景,如运维监控、故障排查等。
  3. 实时数据分析:
    提供了聚合分析功能,可以实现对保存的大量数据的近实时统计分析。适用于需要实时数据分析的应用场景,如商业智能、数据分析等。

四、面试问题

问题1:Elasticsearch中的分片和副本是如何工作的?分片和副本的大小和数量如何影响ES的性能?

1.分片(Shard)

  • 定义:
    分片是Elasticsearch分发数据的单元。每个分片本身就是一个完整的搜索引擎(Lucene实例),它保存了全部数据中的一部分。
  • 创建与分配:
    当创建一个新索引时,Elasticsearch会根据用户指定的分片数量(通过number_of_shards参数)创建主分片,并将这些分片分配到集群中的不同节点上。
    分片的分配由Elasticsearch自动管理,确保它们分布在集群的不同节点上,以最大限度地提高系统的容错能力和性能。
  • 数据写入:
    对于写操作(如创建、更新或删除),Elasticsearch会将请求发送到包含相关分片的节点上执行。
    写请求首先发送到主分片,主分片处理写请求并将数据写入到分片中,然后主分片将写操作同步到所有的副本分片,确保数据的一致性。
  • 数据读取:
    对于读取操作,Elasticsearch可以从任何具有对应分片(无论是主分片还是副本分片)的节点上获取数据。
    这允许查询负载均衡,并且可以利用副本分片来增加搜索吞吐量

2.副本(Replica)

  • 定义:
    副本是对主分片的冗余复制,用于提高数据的可用性和容错性。
    每个主分片都可以有一个或多个副本分片。
  • 创建与分配:
    Elasticsearch根据索引的副本设置(通过number_of_replicas参数),为每个主分片创建副本分片。
    副本分片被分配到与主分片不同的节点上,以确保数据冗余和故障恢复能力。
  • 故障恢复:
    如果某个节点宕机了,导致某些分片不可用,Elasticsearch会自动检测到这个问题并尝试使用副本分片来恢复服务。
    Elasticsearch会将副本分片提升为主分片,并在集群中的其他节点上创建新的副本分片,以恢复数据冗余。
  • 性能提升:
    副本分片可以分担读请求,减少单个分片的读负载,从而提高搜索性能和吞吐量。

3.分片大小和数量对性能的影响

  • 分片大小:
    写入性能 :较小的分片可以减少每个分片上的数据量,从而可能加快写入速度,因为每次写入操作涉及的数据量更少。然而,过小的分片可能导致过多的分片数量,增加管理开销和I/O操作。相反,较大的分片可以处理更多的写入请求,提高系统的写入吞吐量,但过大的分片可能使故障恢复速度变慢。
    读取性能:分片大小对读取性能的影响相对复杂。较小的分片可能减少查询时的数据扫描范围,但也可能增加查询时的分片间通信开销。较大的分片可能提高查询效率,但也可能导致查询延迟增加,因为需要处理的数据量更大。
  • 分片数量:
    写入性能 :更多的主分片可以提高写入吞吐量,因为操作可以并行化到多个分片上。然而,每个分片都会消耗资源(CPU、内存、磁盘),过多的分片会导致资源竞争,反而降低性能。
    读取性能:读取性能可以通过增加副本分片来提高,因为更多的副本可以处理更多的并发读请求。然而,分片数量过多也可能导致查询时的分片间通信开销增加,影响读取性能。

4.副本大小和数量对性能的影响

  • 副本大小

    副本是数据的冗余拷贝,存储在副本分片中。副本分片的大小与主分片相同,因为它们是对主分片的完整复制。因此,副本大小本身对性能没有直接影响,但副本的数量和分布会影响性能。

  • 副本数量

    提示:这里说的副本的数量是指ES对分片复制了几份副本,而不是一份副本有多少个分片。
    读取性能 :增加副本分片数量可以提高系统的读取性能,因为更多的副本可以处理更多的并发读请求。副本分片还可以减少单个分片的读负载,因为请求可以在多个副本之间均匀分配。
    写入性能 :每次写入操作不仅要在主分片上执行,还要在所有副本分片上重复。因此,增加副本分片数量会增加写操作的负担,每次写操作需要同步到更多的副本上。这可能导致写入性能下降,特别是在资源有限的情况下。
    容错能力:副本分片还可以提高系统的容错能力。如果一个节点或分片失败,Elasticsearch可以从副本中恢复数据,几乎不影响用户查询。更多的副本可以更快地恢复数据,因为Elasticsearch有更多选项来重新分配和平衡网络中的数据。

5.优化建议

  • 合理设置分片数量:
    根据数据量、硬件资源和使用场景来设置主分片的数量。通常建议将每个主分片的大小保持在几十GB到几百GB之间。
    对于需要频繁更新或删除的数据,较小的分片(如10GB-20GB)可能更合适,以减少段合并的开销。对于静态数据或只增加不修改的数据,更大的分片(接近50GB)通常更有效。
  • 根据读取负载调整副本数量:
    如果系统是读取密集型的(如搜索或分析应用),增加副本分片可以提供更好的读取性能。
    在决定副本数量时,也要考虑集群的节点数量。至少应该有足够的节点来分配这些副本,以避免所有副本都在同一个节点上导致资源竞争。
  • 监控和调整:
    使用Elasticsearch的监控工具(如Kibana Monitoring)定期检查分片的健康和性能。
    如果检测到性能瓶颈,可以根据具体情况调整分片和副本的数量。例如,使用Shrink API减少分片数量,或使用Split API增加分片数量。

问题2:ES的整体架构是怎样的?

Elasticsearch(简称ES)的整体架构是分布式和模块化的,旨在支持大规模数据的搜索、分析和实时查询

1. 上半部分呢:

上半部分是ES中部署的集群节点。
节点类型 :主节点、数据节点、协调节点或备份节点。
分片类型:一个索引可以分为多个分片,分散在不同的机器上。分片有主分片和副分片,当主分片出现故障时,副本分片会自动提升为主分片,以继续提供服务。

2.下半部分呢

下半部分主要是ES作为一个实时搜索引擎的原理。
存储机制 :当文档被写入Elasticsearch时,它们首先被存储在内存缓冲区(Memory Buffer)中。然后,这些文档会定期被刷新到磁盘上的段文件(Segment)中。段文件是Lucene索引的基本单位,它们包含了文档的倒排索引和其他相关信息。
检索机制 :当用户执行搜索查询时,Elasticsearch会首先在Term Dictionary中查找查询字符串中的每个单词。然后,它会使用这些单词对应的倒排列表来找到包含这些单词的文档。最后,系统会根据文档的相关性得分对结果进行排序并返回给用户。倒排索引允许Elasticsearch快速定位到包含特定单词的文档集合。
分布式架构 :Elasticsearch的分布式架构允许它横向扩展,以支持大规模数据集的存储与处理。通过添加更多节点到集群中,Elasticsearch可以自动重新分配数据以平衡负载并提高性能。
扩展性:Elasticsearch提供了灵活的扩展选项,包括垂直扩容(使用更强大的服务器)和水平扩容(添加更多服务器)。然而,水平扩容通常是更受欢迎的选择,因为它可以更有效地利用资源并避免单点故障。

问题3:ES的倒排索引是如何实现的?

Elasticsearch使用倒排索引(Inverted Index)来存储和检索数据。倒排索引是一种数据结构,用于存储每个词(term)及其对应的文档ID列表(Posting List)。这种结构使得Elasticsearch能够快速地根据一个或多个词找到包含这些词的文档。

1.Term Dictionary

Elasticsearch将所有的词进行排序,并使用二分法查找词,以提高查找效率。这种排序后的词列表被称为Term Dictionary。

  • 正排索引的Term Dictionary
    正排索引的Term Dictionary是以文档的ID作为关键字,并且记录文档中每个字段的值信息,通过查询id来把整条文档拿出来。但是在查询某一个keyword存在于哪些文档的时候, 需要对所有文档进行扫描匹配。
  • 倒排索引的Term Dictionary
    倒排索引的Term Dictionary,倒排索引以字或词作为关键字索引, 倒排索引建立的是分词(Term)和文档(Document)之间的映射关系

2.倒排列表(Posting List)

倒排列表记载了出现过某个单词的所有文档的文档列表。

列表中包含单词在该文档中出现的位置信息及频率(作关联性算分),每条记录称为一个倒排项(Posting)

3.Term Index

由于Term Dictionary可能非常大,无法全部放入内存,因此Elasticsearch引入了Term Index。Term Index类似于字典的索引页,它包含了词的一些前缀和对应的Term Dictionary的block位置。通过Term Index,Elasticsearch可以快速定位到Term Dictionary的某个位置,然后从这个位置顺序查找所需的词。

4.FST(Finite State Transducers)

为了进一步优化Term Index,Elasticsearch使用了FST压缩技术。FST是一种有限状态机,它将词(字节序列)映射到任意输出。通过FST,Elasticsearch可以将Term Index占用的空间进一步缩小并缓存到内存中,从而提高查找效率。

问题4:ES写入文档的过程是怎么样的吗?

在ES中,索引(Index)是一个逻辑命名空间,包含一组文档。每个索引由多个分片(Shard)组成,而每个分片又由多个segment组成。

segment是索引数据的实际存储单元,而分片则是数据分布和并行处理的基本单位。当查询一个Elasticsearch索引时,查询会在所有分片上执行,进而查询到segment,然后合并所有结果。每一个段都是一个独立的、不可变的文件集合,包含了完整索引中的一部分数据(包括倒排索引和正排索引)。

为了提升写的性能,Lucene并没有每新增一条数据就增加一个段,而是采用延迟写的策略,每当有新增的数据时,就将其先写入内存中,然后批量写入磁盘中。若有一个段被写到硬盘,就会生成一个提交点,提交点就是一个列出了所有已知段和记录所有提交后的段信息的文件

1.写入请求的接收与路由

  • 接收请求

    客户端向Elasticsearch集群中的任意节点发送写入(Index)请求

  • 确定目标分片

    接收请求的节点(作为协调节点)根据文档的ID和索引的设置(如分片数量),使用哈希函数和模运算来确定文档应该写入到哪个主分片。

    分片计算公式:shard_num = hash(_routing) % num_primary_shards。其中,_routing默认情况下是文档的ID,num_primary_shards是主分片的数量

  • 路由请求到目标节点

    协调节点根据目标分片的ID,通过集群状态中的路由表找到该分片的主分片所在的节点,并将请求转发给该节点

2. 在主分片上执行写入操作

  • 内存缓冲区

    主分片接收到写入请求后,首先将文档存储在内存中的一个缓冲区(In-memory buffer)中

  • 记录事务日志

    同时,为了确保数据的持久性和可靠性,Elasticsearch将每个写入操作记录到事务日志(Translog)中。

    Translog是一个追加写入的日志文件,它记录了所有对索引的更改,以便在系统崩溃后恢复数据。

  • 创建倒排索引

    在内存缓冲区中,Elasticsearch将文档转换成倒排索引的形式,这个索引会在内存中形成一个分段对象(Segment),详情见下方的刷新操作(Refresh)。

    倒排索引是Elasticsearch高效搜索的关键,它记录了每个单词在哪些文档中出现,以及出现的位置。

3. 将数据同步到副本分片

  • 异步复制
    一旦文档被写入到主分片,主分片会开始将数据异步地同步到其对应的副本分片上。
    副本分片是主分片的完整拷贝,它们可以处理搜索请求并提供数据恢复的能力。
  • 等待确认
    主分片等待所有副本分片都成功写入文档后,才向协调节点发送确认信息。
    Elasticsearch的写入一致性策略(如quorum)确保了在写入数据时,必须有足够数量的活跃分片(包括主分片和副本分片)处于可用状态。

4. 刷新与持久化

  • 刷新操作(Refresh):
    刷新操作会将内存缓冲区中的数据创建成一个新的Lucene段(Segment),并将其添加到索引中。
    刷新操作是周期性的,可以通过配置来控制刷新的频率,它使得新写入的数据可以被搜索到,但它不会将数据持久化到磁盘上。
  • 持久化操作(Flush):
    持久化操作会将内存中的数据以及Translog中的更改写入到磁盘上。
    这意味着数据被真正写入到了物理存储中,而不仅仅是保存在操作系统的文件系统缓存中。
    持久化操作会调用操作系统的fsync函数来确保数据被写入磁盘,并且会清空相关的缓存和文件(如Translog)。

5. 合并段(Segment Merging)

  • 优化存储和搜索性能

    ElasticSearch 每次 refresh 一次都会生成一个新的 segment 文件,这样下来 segment 文件会越来越多。因为每一个 segment 都会占用文件句柄、内存、cpu资源,每个搜索请求都必须访问每一个segment,这就意味着存在的 segment 越多,搜索请求就会变得更慢。

    为了优化存储和搜索性能,Lucene会定期进行段合并操作。

    小的段会被合并到大的段中,然后这些大的段再被合并到更大的段。

  • 合并过程

    合并过程在后台进行,不会中断索引和搜索操作。ElasticSearch 有一个后台进程专门负责 segment 的合并,定期执行 merge 操作,将多个小 segment 文件合并成一个 segment,在合并时被标识为 deleted 的文档不会被写入到新的 segment 中。

    合并完成后,老的段会被删除,然后将新的 segment 文件 flush 写入磁盘。

    然后创建一个新的 commit point 文件,标识所有新的 segment 文件,并排除掉旧的 segement 和已经被合并的小 segment。

问题:ES在高并发下如何保证读写一致性?

1. 最终一致性模型

Elasticsearch采用最终一致性模型,这意味着在理想情况下,系统会最终达到一致性,但可能在某些情况下会有短暂的不一致,尤其是在分布式系统中发生网络分区或节点故障时。这种模型提供了高可用性和容错能力,同时降低了严格一致性带来的性能开销。

2. 事务日志(Translog)

  • 作用:记录所有对索引的更改操作,包括文档的插入、更新和删除。

  • 写前日志(Write-Ahead Logging, WAL):当写入请求到达时,Elasticsearch首先将数据写入事务日志,然后再将其异步刷新到磁盘上的分片中。这种机制确保了在系统崩溃等异常情况下,已经提交的数据不会丢失。

  • 持久化:事务日志的使用对于处理高并发写入请求至关重要,因为写入操作只需要写入事务日志,而不需要直接更新磁盘上的分片,因此写入性能得到了极大的提升。同时,定期将事务日志的内容写入到一个新的日志文件中,并删除旧的日志文件,以确保数据的持久化。

3. 分片和副本

  • 分片:Elasticsearch通过将数据分布在多个分片上来实现水平扩展。每个索引由一个或多个分片组成,每个分片可以独立存储和处理数据。这种分片机制有助于将写入和读取请求分散到集群的不同节点上,从而提高并发处理能力。

  • 副本:每个分片可以有零个或多个副本。副本是分片的完整拷贝,用于提高数据的可用性和容错能力。当原始分片不可用时(例如,由于节点故障),副本可以接管处理请求。通过合理配置分片和副本的数量,可以在集群中平衡负载,进一步提高并发处理能力。

4. 乐观并发控制

  • 版本号:Elasticsearch在每个文档上维护版本号。每当文档被更新时,该版本号就会增加。

  • 写入操作:当写入操作请求使用一个特定版本时,Elasticsearch会检查当前存储的版本与请求的版本是否匹配。如果匹配,则执行更新操作;如果不匹配,则返回版本冲突错误。

  • 冲突处理:如果两个并发请求试图更新同一个文档,只有第一个请求会成功,第二个请求会收到一个版本冲突错误。应用程序可以根据业务逻辑对这些冲突进行处理,比如重试或者合并数据

5.写入一致性和读取一致性控制

  • 写入一致性:通过设置write consistency,可以要求在写操作时,必须等待多少个分片副本确认成功才能返回。这可以提高数据的可靠性,但可能会增加延迟。例如:
    • quorum:等待多数副本确认。
    • all:等待所有副本确认。
  • 读取一致性:通过设置search consistency,可以保证读取到的数据是某个时间点的一致视图。例如:
    • 使用refresh机制,确保查询时能够看到刚刚写入的数据。
    • 在分页查询时,可以使用search_after进行基于游标的查询,以避免由于分页查询中的数据变化导致的不一致问题。
相关推荐
奥顺1 小时前
从零开始:PHP基础教程系列-第10篇:错误处理与调试技巧
大数据·mysql·开源·php
知识分享小能手3 小时前
Java学习教程,从入门到精通,Java Stack(堆栈)语法知识点及语法知识点(58)
java·大数据·开发语言·学习·intellij-idea·java后端·java开发
xyz20113 小时前
Flink State面试题和参考答案-(上)
大数据·面试·flink
代码欢乐豆5 小时前
NoSQL大数据存储技术测试(7)键值对数据库Redis和其他NoSQL数据库
大数据·数据库·nosql
꧁薄暮꧂5 小时前
Apache Kylin最简单的解析、了解
大数据·kylin
Ekine8 小时前
【Flink-scala】DataStream编程模型之延迟数据处理
大数据·flink·scala
CodeCraft Studio14 小时前
什么是定性数据分析?有哪些定性数据分析技术及应用实践?
大数据·人工智能·数据分析
ssxueyi15 小时前
Flink是什么?Flink技术介绍
大数据·flink
Lyqfor15 小时前
Apache Spark 的基本概念和在大数据分析中的应用
大数据·spark·apache