简述Elasticsearch 的底层存储原理?
参考回答
Elasticsearch 的底层存储原理依赖于 Lucene,它是 Elasticsearch 的核心搜索引擎。Lucene 提供了高效的全文索引和搜索功能,而 Elasticsearch 则在其基础上增加了分布式、集群管理等功能。下面是 Elasticsearch 底层存储原理的主要组成部分:
- 倒排索引(Inverted Index):
- 倒排索引是 Elasticsearch 高效搜索的核心数据结构。在倒排索引中,文档中的每个词(或词条)都会被映射到一个或多个包含该词的文档。这使得 Elasticsearch 能够在查询时快速定位包含特定词的文档,从而大大提高检索效率。
- 举个例子,假设我们有以下两篇文档:
- 文档1:
The quick brown fox
- 文档2:
Jumped over the lazy dog
倒排索引会记录每个词的出现位置:
the
-> [文档1, 文档2]quick
-> [文档1]brown
-> [文档1]fox
-> [文档1]jumped
-> [文档2]over
-> [文档2]lazy
-> [文档2]dog
-> [文档2]
通过倒排索引,Elasticsearch 可以快速查找到包含特定词条的文档。
- 文档1:
-
文档存储与字段存储:
- Elasticsearch 中的每个文档是以 JSON 格式存储的,文档包含多个字段,每个字段代表了文档的一个数据项。文档数据会被存储在磁盘上,并且 Elasticsearch 会为每个字段建立索引。
- 文档中的每个字段可以具有不同的数据类型,如文本、数值、日期等,Elasticsearch 会根据字段类型来决定如何存储和索引该字段的值。
- 段(Segment):
- Elasticsearch 将数据存储在 段(Segment) 中,段是 Lucene 的最小索引单元。每个段是一个不可变的索引,包含了文档及其字段的所有信息。
- 当 Elasticsearch 执行写入操作时,数据会首先写入到内存中的缓冲区(称为 Translog),当缓冲区数据达到一定阈值时,Elasticsearch 会将这些数据刷新到磁盘并形成一个新的段。
- 段是只读的,一旦创建,不能修改。新的更新操作会在新的段中创建一个新的文档。如果有删除操作,文档会被标记为删除,直到段合并时才会被实际移除。
- 段合并(Segment Merging):
- 为了提高存储效率和查询性能,Elasticsearch 会定期执行段合并操作。合并操作会将多个小的段合并为一个大的段,去除标记为删除的文档,并且将所有文档重新排序。这样,段合并可以减少磁盘空间的占用,并提升查询效率。
- 合并操作是一个后台操作,它会在后台进行,而不会影响前端的查询请求。
- Doc Values:
- Elasticsearch 为某些字段(如数值、日期和关键字字段)提供了 Doc Values。Doc Values 是一种列式存储格式,它与倒排索引结合使用,优化了对这些字段的聚合、排序和过滤操作。
- 列式存储意味着 Doc Values 会将字段的值按列存储,而不是按行存储。这样可以更高效地进行聚合和排序操作,因为只需要扫描特定列的数据,而不是整个文档。
- 事务日志(Translog):
- 在 Elasticsearch 中,每个写操作(如索引文档、更新或删除文档)都会先写入到 事务日志(Translog) 中,事务日志记录了所有对文档的修改。事务日志确保了即使在系统崩溃时,最近的写入操作也不会丢失。
- 当文档被刷新到磁盘时,相关的写入操作会从事务日志中删除。这有助于确保数据的一致性和可靠性。
- Sharding 和 Replication:
- Elasticsearch 是一个分布式系统,数据被分为多个 分片(Shard)。每个分片是一个独立的 Lucene 索引,负责存储和检索数据。数据的分片有助于 Elasticsearch 扩展到多个节点。
- 每个分片还可以有多个 副本(Replica),副本是分片的完整复制。副本的存在可以提高系统的可用性和查询性能。
详细讲解与拓展
1. 倒排索引
- 倒排索引在 Elasticsearch 中的核心作用是加速查询。它允许系统根据单个词条快速定位到包含该词的文档,而无需扫描整个文档。倒排索引是全文搜索引擎的标准数据结构,通过建立词到文档的映射,倒排索引可以显著提高搜索速度。
-
例子:
假设有三个文档:The quick brown fox
Jumped over the lazy dog
The lazy fox jumped over the brown dog
在倒排索引中,”fox” 这个词会指向包含它的文档编号。例如,倒排索引中 “fox” 对应的文档列表可能是
[1, 3]
,表示 “fox” 出现在文档 1 和文档 3 中。
2. 段合并
- 段合并的主要目的是减少不必要的小段,提升查询效率和磁盘存储利用率。Elasticsearch 会周期性地合并段,合并时删除标记为删除的文档,并优化索引结构。
- 段合并操作并不立即影响正在进行的查询,而是在后台悄悄进行。每个段都需要被读取才能执行查询,但段合并可以减少读取的段数量,从而加快查询速度。
3. Doc Values 和列式存储
-
对于需要进行排序、聚合或范围查询的字段,Elasticsearch 使用了 Doc Values 来优化这些操作。与传统的行式存储(按文档存储字段)不同,列式存储可以将字段的所有值按列存储,从而提高聚合和排序的效率。
-
例子:
如果你有一个price
字段,Doc Values 会将所有文档的价格按列存储。当进行价格排序时,Elasticsearch 只需要扫描这列数据,而不需要扫描整个文档,从而大大提高了性能。
4. 分片和副本
-
数据分片是 Elasticsearch 的一个重要特性,它将数据分散到多个节点上,支持水平扩展。每个分片是一个独立的 Lucene 索引,这样可以分担查询和索引的负载。
-
副本的作用不仅仅是提供数据冗余,还能提高查询性能,因为副本也可以处理查询请求。因此,当一个节点无法提供服务时,副本可以确保数据不会丢失,查询请求仍然能够正常响应。
总结
Elasticsearch 的底层存储原理基于 Lucene,利用倒排索引、段合并、Doc Values 等技术来优化数据存储和查询性能。通过分片和副本机制,Elasticsearch 支持分布式存储和计算,能够处理大规模数据。段合并和事务日志确保了数据的一致性和可靠性,而列式存储则优化了聚合和排序操作。通过这些技术,Elasticsearch 能够高效地存储和查询海量数据。