上篇文章提到过,在elasticsearch和磁盘之间还有一层cache也就是filesystem cache,大部分新增或者修改,删除的数据都在这层cache中,若是没有flush操做,那么就不能100%保证系统的数据不会丢失,好比忽然断电或者机器宕机了,但实际状况是es中默认是30分钟才flush一次磁盘,这么长的时间内,若是发生不可控的故障,那么是否是一定会丢失数据呢?api
很显然es的设计者早就考虑了这个问题,在两次full commit操做(flush)之间,若是发生故障也不能丢失数据,那么es是如何作到的呢?异步
在es里面引入了transaction log(简称translog),这个log的做用就是每条数据的任何操做都会被记录到该log中,很是像Hadoop里面的edits log和hbase里面的WAL log,以下图: async
transaction log的工做流程以下:elasticsearch
(1)当一个文档被索引时,它会被添加到内存buffer里面同时也会在translog里面追加oop
(2)当每一个shard每秒执行一次refresh操做完毕后,内存buffer会被清空但translog不会。性能
过程以下:大数据
2.1 当refresh动做执行完毕后,内存buffer里面的数据会被写入到一个segment里面,这个还在cache中,并无执行flush命令 2.2 新生成的segment在cache中,会被打开,这个时候就能够搜索新加的数据 2.3 最后内存buffer里面的数据会被清空
上面过程以下图: 优化
(3)随着更多的document添加,内存buffer区会不断的refresh,而后clear,但translog数量却越增越多,以下图:设计
(4)当达到默认的30分钟时候,translog也会变得很是大,这个时候index要执行一次flush操做,同时会生成一个新的translog文件,而且要执行full commit操做,流程以下:3d
4.1 内存buffer里的全部document会被生成一个新的segment 4.2 而后segment被refresh到系统cache后,内存buffer会被清空 4.3 接着commit point会被写入到磁盘上 4.4 filesystem cache会被flush到磁盘上经过fsync操做 4.5 最后旧的translog会被删除,并会生成一个新的translog
以下图:
tanslog的做用就是给全部尚未flush到硬盘上的数据提供持久化记录,当es重启时,它首先会根据上一次中止时的commit point文件把全部已知的segments文件给恢复出来,而后再经过translog文件把上一次commit point以后的全部索引变化包括添加,删除,更新等操做给重放出来。
除此以外tanslog文件还用于提供一个近实时的CURD操做,当咱们经过id读取,更新或者删除document时,es在从相关的segments里面查询document以前,es会首先从translog里面获取最近的变化,这样就意味着es老是近实时的优先访问最新版本的数据。
咱们知道执行flush命令以后,全部系统cache中的数据会被同步到磁盘上而且会删除旧的translog而后生成新的translog,默认状况下es的shard会每隔30分钟自动执行一次flush命令,或者当translog变大超过必定的阈值后。
flush命令的api以下:
POST /blogs/_flush //flush特定的index POST /_flush?wait_for_ongoing//flush全部的index知道操做完成以后返回响应
flush命令基本不须要咱们手动操做,但当咱们要重启节点或者关闭索引时,最好提早执行如下flush命令做为优化,由于es恢复索引或者从新打开索引时,它必需要先把translog里面的全部操做给恢复,因此也就是说translog越小,recovery恢复操做就越快。
咱们知道了tangslog的目的是确保操做记录不丢失,那么问题就来了,tangslog有多可靠?
默认状况下,translog会每隔5秒或者在一个写请求(index,delete,update,bulk)完成以后执行一次fsync操做,这个进程会在全部的主shard和副本shard上执行。 这个守护进程的操做在客户端是不会收到200 ok的请求。
在每一个请求完成以后执行一次translog的fsync操做仍是比较耗时的,虽然数据量可能比并非很大。 默认的es的translog的配置以下:
"index.translog.durability": "request"
若是在一个大数据量的集群中数据并非很重要,那么就能够设置成每隔5秒进行异步fsync操做translog,配置以下:
PUT /my_index/_settings { "index.translog.durability": "async", "index.translog.sync_interval": "5s" }
上面的配置能够在每一个index中设置,而且随时均可以动态请求生效,因此若是咱们的数据相对来讲并非很重要的时候,咱们开启异步刷新translog这个操做,这样性能可能会更好,但坏的状况下可能会丢失5秒以内的数据,因此在设置以前要考虑清楚业务的重要性。
若是不知道怎么用,那么就用es默认的配置就行,在每次请求以后就执行translog的fsycn操做从而避免数据丢失。