文章目录
前言
上一章我们介绍了倒排索引的数据结构。
本章我们将深入介绍 Lucene 写入流程。
该知识点在面试中比较常问,也是理解 ES 必须掌握的知识点。
写入流程图
在第 14 章,我在介绍 coordinating node
时,画了 coordinating node
的工作流图,但是只画到了 data node
。
那么当数据到达 data node
后,ES 是如何将数据写入的呢?
我们来看一个 ES 比较完整的写入流程图
图中标红的地方,就是我们要详细讲解的内容。
从图中,我们可以知道:
- 1 个
Data Node
可以有非常多的Lucene
实例 - 1 个分片就是一个
Lucene
实例(ES 是基于Apache Lucene
开发的) - 1 个
Segement
就是一个倒排索引
refresh
数据写入时,先写入到内存,此时这部分数据无法被检索。Refresh
后, 数据就能被检索。这也是为什么 ES 被称为 近实时查询
的原因。
当发生 Refresh
时,数据会被写入操作系统 file cache
,并清空 Memory buffer
。
这里,我们不禁要产生疑问了:
- 什么时候触发
Refresh
? Refresh
只是将数据写入file cache
,但file cache
在操作系统掉电或崩溃后,数据会丢失的,这怎么办?
Refresh 触发时机
Memory Buffer
满refresh_interval
(创建索引时可以指定) 时间到
Translog
为了避免 file cache
掉电或崩溃后数据丢失。ES 在触发 Refresh
时,同时还会写入 translog
,用于恢复未落盘的数据。
translog
具有以下几个特点:
- 顺序写入,写入速度快
- 每个分片都有对应的
translog
translog
默认每次索引写入时落盘- 触发 flush 后,
translog
会被清空(segment 都落盘了,旧的translog
肯定没用了)
Flush
Flush
阶段的作用是执行 fsync
, 将 segment
落盘。
ES 默认每隔 30 分钟执行 1 次 Flush
操作,执行内容如下:
- 执行 Refresh
- 清空 translog
Merge
你可能也注意到了,每次写入都不会去修改旧的 segment,而是生成新的 segment(segment 不可变)。也因此,segment 是一个不断增多的过程。
当 segment
增多的时候,ES 查询性能会下降,因此需要定时的合并 segment
。
Merge 是 ES 内部自动处理的。当然我们可以强制让 ES 执行 Merge,也可以控制 Merge 时的并发线程。
-
强制 Merge
POST /{your-index}/_forcemerge
-
控制并发线程
index.merge.scheduler.max_thread_count
。该配置默认值为:Math.max(1, Math.min(4, <<node.processors>> / 2))