1. 前言
如果没有用 fsync
把数据从文件系统缓存刷(flush
)到硬盘,我们不能保证数据在断电甚至是程序正常退出之后依然存在。为了保证 Elasticsearch 的可靠性,需要确保数据变化被持久化到磁盘。
在动态更新索引,我们说一次完整的提交会将段刷到磁盘,并写入一个包含所有段列表的提交点
。Elasticsearch 在启动或重新打开一个索引的过程中使用这个提交点来判断哪些段隶属于当前分片。
即使通过每秒刷新(refresh
)实现了近实时搜索,我们仍然需要经常进行完整提交来确保能从失败中恢复。但在两次提交之间发生变化的文档怎么办?我们也不希望丢失掉这些数据。
Elasticsearch 增加了一个 translog
,或者叫事务日志
,在每一次对 Elasticsearch 进行操作时均进行了日志记录。
2. refrash
与flush
通过 translog
,整个流程看起来是下面这样:
一个文档被索引之后,就会被添加到内存缓冲区,并且追加到了 translog
,正如 Figure 21
, “新的文档被添加到内存缓冲区并且被追加到了事务日志”
描述的一样。
Figure 21. 新的文档被添加到内存缓冲区并且被追加到了事务日志
2.1 refrash
刷新(refresh
)使分片处于 Figure 22, “刷新(refresh)完成后, 缓存被清空但是事务日志不会”
描述的状态,分片每秒被刷新(refresh
)一次:
- 这些在内存缓冲区的文档被写入到一个新的段中,且没有进行
fsync
操作。 - 这个段被打开,使其可被搜索。
- 内存缓冲区被清空。
Figure 22. 刷新(refresh)完成后, 缓存被清空但是事务日志不会
这个进程继续工作,更多的文档被添加到内存缓冲区和追加到事务日志(见 Figure 23, “事务日志不断积累文档”
)。
Figure 23. 事务日志不断积累文档
2.2 flush
每隔一段时间—例如 translog
变得越来越大—索引被刷新(flush
);一个新的 translog
被创建,并且一个全量提交被执行(见 Figure 24, “在刷新(
flush)之后,段被全量提交,并且事务日志被清空”
):
- 所有在内存缓冲区的文档都被写入一个新的段。
- 缓冲区被清空。
- 一个提交点被写入硬盘。
- 文件系统缓存通过
fsync
被刷新(flush
)。 - 老的
translog
被删除。
translog
提供所有还没有被刷到磁盘的操作的一个持久化纪录。当 Elasticsearch 启动的时候, 它会从磁盘中使用最后一个提交点去恢复已知的段,并且会重放 translog
中所有在最后一次提交后发生的变更操作。
translog
也被用来提供实时 CRUD
。当你试着通过ID
查询、更新、删除一个文档,它会在尝试从相应的段中检索之前, 首先检查 translog
任何最近的变更。这意味着它总是能够实时地获取到文档的最新版本。
Figure 24. 在刷新(flush)之后,段被全量提交,并且事务日志被清空
3. flush API
这个执行一个提交并且截断 translog
的行为在 Elasticsearch 被称作一次 flush
。 分片每30分钟
被自动刷新(flush
),或者在 translog
太大的时候也会刷新。请查看 translog
文档 来设置,它可以用来 控制这些阈值:
flush API
可以被用来执行一个手工的刷新(flush
):
POST /blogs/_flush
POST /_flush?wait_for_ongoing
- 刷新(
flush
) blogs 索引。 - 刷新(
flush
)所有的索引并且并且等待所有刷新在返回前完成。
你很少需要自己手动执行 flush 操作;通常情况下,自动刷新就足够了。
这就是说,在重启节点或关闭索引之前执行 flush
有益于你的索引。当 Elasticsearch 尝试恢复或重新打开一个索引, 它需要重放 translog
中所有的操作,所以如果日志越短,恢复越快。