数据写入ES集群,主要是经过以下2个主要步骤:

1. 读取数据 -> 验证(master节点分发给data节点处理,或直接访问data节点主分片) 

2. 同时写入buffer缓冲区和translog日志文件 -> 生成segment file -> 合并小segment file生成大segment file -> 将合并的segment file刷写到系统缓存,此时可以数据可以被搜索到(refresh) -> 用fsync将所有缓存数据刷写到磁盘(flush)

es 插入数据 index java es数据写入流程_es 插入数据 index java

一、refresh操作

1. translog文件的功能

(1)保证在filesystem cache中的数据不会因为elasticsearch重启或是发生意外故障的时候丢失。

(2)当系统重启时会从translog中恢复之前记录的操作。

(3)当对elasticsearch进行CRUD操作的时候,会先到translog之中进行查找,因为tranlog之中保存的是最新的数据。

(4)translog的清除时间在进行flush操作之后(将数据从filesystem cache刷入disk之中)。

translog文件就是ES近实时的关键所在,新增的索引的文档数据在buffer内存缓冲区中,以segment文件存在时,是不能被搜索到的;

只有translog文件控制segment文件refresh到缓存cache中,才可以被搜索到;

index.refresh_interval这个参数,就是控制文件refresh到缓存cache中的时间间隔,当index.refresh_interval所定义的时间达到后,translog文件触发segment的refresh,默认这个参数是1s,所以ES的数据从写入到被查询到有1s的延迟。

2. 执行refresh操作

文档从segment到cache这个过程被称为refresh

这个过程中,合并的segment文件写入cache,然后segment文件被打开可以被搜索到,最后清空buffer缓冲区,供下一次文档数据的写入

refresh的开销比较大,10w的数据refresh一次大概要14ms,因此在大批量写入数据时,可以把refresh间隔调为-1,这样只有当缓冲区的数据达到一定大小(默认是jvm的10%)后才会发生一次refresh;

等数据写完后再重新设置为30s左右,这个优化依赖于数据量和集群情况,如果写入的数据量太大,可能会对内存造成比较大的压力,具体表现就是集群的data节点负载过高,如果大批量写入时对时间要求非常高,并且写时查询要求也不高,集群健康的前提下也可以设置为-1。

另外数据写入时,建议把副本分片数设置0,等数据写入后再改回1,这样写数据就不是同时写两份,耗时会大幅度降低。

二、flush操作

es默认每隔30分钟会将filesystem cache中的数据刷入磁盘同时清空translog日志文件,因此此时内存中的segments已经写入到磁盘中,就不需要translog来保障数据安全了,这个过程叫做flush。

1.es的各个shard会每个30分钟进行一次flush操作。

2.当translog的数据达到某个上限的时候会进行一次flush操作。

有关于translog和flush的一些配置项:

index.translog.flush_threshold_ops:当发生多少次操作时进行一次flush。默认是无限制。

index.translog.flush_threshold_size:当translog的大小达到此值时会进行一次flush操作。默认是512mb,可以改为1024mb。

index.translog.sync_interval:多少时间间隔内会检查一次translog,来进行一次flush操作。默认是5s,可以改为100s。

index.translog.durability:flush的方式,改为async,写入耗时更低。

上面的参数是es多久执行一次flush操作,在系统恢复过程中es会比较translog和segments中的数据来保证数据的完整性,为了数据安全es默认每隔5秒钟会把translog刷新(fsync)到磁盘中,也就是说系统掉电的情况下es最多会丢失5秒钟的数据。

flush是把内存中的数据(包括translog和segments)都刷到磁盘,而fsync只是把translog刷新的磁盘(确保数据不丢失)。