分片内部细节-段和持久化

date
Aug 1, 2021
slug
elasticsearch-guide-segment-persistence
status
Published
tags
Elasticsearch
读书
summary
type
Page
理解下面几个问题
  • 为什么搜索是  实时 near real-time 的
  • 为什么文档的 CRUD (创建-读取-更新-删除) 操作是 实时 的?
  • Elasticsearch 是怎样保证更新被持久化在断电时也不丢失数据?
  • 为什么删除文档不会立刻释放空间?
  • refreshflush, 和 optimize API 都做了什么,你什么情况下应该使用他们?
 

倒排索引不可变 Immutable

倒排索引一旦写入就不可改变,不可变的好处:
  • 不需要锁。
  • 缓存利用率高,性能很大提升。
  • 其它缓存(像 filter 缓存),在索引的生命周期内始终有效。它们不需要在每次数据改变时被重建,因为数据不会变化。
  • 写入单个大的倒排索引允许数据被压缩,减少磁盘 I/O 和需要被缓存到内存的索引的使用量。
坏处:
  • 限制了一个索引能够包含的最大数据量
  • 对索引的更新频率有限制
 

引入 Lucene 及其相关概念:

Elasticsearch 的索引 = Elasticsearch 分片的集合
Elasticsearch 中的分片 = Lucene 实例 ≈ Lucene 索引 = Lucene 段的集合 + commit point
Lucene 实例中主要的就是倒排索引结构
来自文档的说明:
"Index Versus Shard:To add to the confusion, a Lucene index is what we call a shard in Elasticsearch, while an index in Elasticsearch is a collection of shards. When Elasticsearch searches an index, it sends the query out to a copy of every shard (Lucene index) that belongs to the index, and then reduces the per-shards results to a global result set, as described in Distributed Search Execution."
图示是一个 Lucene Index,它含有三个段 segment 和一个 commit point。
notion image
 

文档写入的过程

首先,文档被写入到内存缓冲队列中 in-memory buffer,同时还会记录到 translog 文件中。
translog 或者叫 transaction log 会记录 Elasticsearch 中每一条操作。
notion image
 
其次,Elasticsearch 定时执行 refresh 操作,将文档从 in-memory buffer 中清除,并打开(理解为新生成)一个 Lucene 段 segment,此时文档存储在文件系统缓存 filesystem cache 中,此时还未完全提交 full commit,但文档已经可以被搜索到了。refresh 间隔默认是 1s。refresh 保证了近实时搜索。
notion image
 
最后,每隔一段时间或者当 translog 过大时,会执行 flush 操作 (size 大小由 index.translog.flush_threshold_size 控制,默认 512M),其会先执行 refresh,将 in-memory buffer 中的文档生成 segment 中,再调用 Lucene 的 commit 方法将未提交的所有 segment 通过系统调用 fsync 写入到磁盘,之后清空 translog,完成持久化。
notion image
 
为什么 30 分钟才 flush ?因为 flush 代价较大,不适合频繁调用。而 Lucene 允许新段被写入和打开使其包含的文档在未进行一次完整提交时便对搜索可见。 这种方式比进行一次提交代价要小得多,并且在不影响性能的前提下可以被频繁地执行。
 
refresh 间隔可以设置:
 

translog 其他用处

可用于恢复数据
如果系统异常宕机,恢复时可以找到最近一次的 commit point,而在 translog 中就是提交点之后的文档且均是未完成提交的,针对性恢复即可。
 
用于实现实时的 CRUD 操作
在 CRUD 时会先在 translog 中检查最新的变更,这也意味着实时访问最新版本的文档。
“The translog is also used to provide real-time CRUD. When you try to retrieve, update, or delete a document by ID, it first checks the translog for any recent changes before trying to retrieve the document from the relevant segment. This means that it always has access to the latest known version of the document, in real-time.”
 

段合并

每一个段都会消耗文件句柄、内存和 CPU 运行周期,频繁创建段会带来性能压力。段越多,搜索也就越慢。Elasticsearch 通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。
notion image
段合并的时会将已标记删除的文档从文件系统中清除。
notion image
使用 optimize 手动强制合并段,一般在处理日志这种永远不变的数据比较适合。
 
参考
深入理解Elasticsearch写入过程:https://zhuanlan.zhihu.com/p/94915597
Elasticsearch内核解析 - 写入篇:https://zhuanlan.zhihu.com/p/34669354
 

© 菜皮 2020 - 2023