一、Refresh操作
默认情况下,Elasticsearch写入的数据会存在于内存缓冲区中,此时并没有落入segment,而是等待index.refresh_interval的时间间隔后,数据会落入到segment中,此时才可以被检索;
而refresh操作简而言之就是将内存缓冲区的数据刷入segement中,使其可以被索引;而默认情况下es配置index.refresh_interval为1s,即每1s将缓冲区的数据刷到segment中使其可以被索引,也就是es所称的实时搜索;
ES会进行默认配置的refresh,但执行index ,Update , Delete , Bulk 操作时提供了可以手动指定refresh 的值,比如
PUT /test/_doc/1?refresh=true
{"field": "test"}
PUT /test/_doc/1?refresh=false
{"field": "test"}
PUT /test/_doc/1?refresh=wait_for
{"field": "test"}
在这时写入数据会同时执行refrsh的操作,总共有三种策略
1.true
2.false(默认)
3.wait_for:等待index.refresh_interval时间,使其自动refresh后响应返回
当我们的某个索引,不需要实时搜索的时候,我们可以调整index.refresh_interval的时间间隔,让其节省资源,在插入数据的时候进行显式的指定refresh=true;
二、Flush操作
flush操作就是将segment中的数据刷入磁盘当中;
需要注意的是,在flush操作前会进行refresh的操作,确保当前的内存缓冲区数据也可以成功落盘;
而说到这里就需要提到trans log的问题,translog是elasticsearh在数据写入内存缓冲区时,同步写入的日志;可以称其为防丢日志; 他的作用是保证在内存缓冲区而未刷入segment中的数据不会因为意外而丢失,如果出现意外也可以通过translog来进行数据的恢复,从而保证形成segment;
而flush操作可以内存缓冲区的数据刷新到segment中,并将segment刷入到磁盘中,而同时会删除当前的translog;
总的来说,当我们执行flush的时候同时执行以下操作
- 把所有在内存缓冲区中的文档写入到一个新的segment中
- 清空内存缓冲区
- 往磁盘里写入commit point信息
- 将segment数据落盘
- 删除旧的translog文件,因此此时内存中的segments已经写入到磁盘中,就不需要translog来保障数据安全了
一般情况下,对于批量导入大量数据到ElasticSearch的某个索引后,推荐进行手动的flush操作,可以释放掉多余的trans log的空间;(但注意,当索引正在执行flush操作时,可能会对性能产生一定的影响,因为系统需要同时处理磁盘IO和搜索请求。所以如果非大量数据导入后清理空间,不推荐频繁的进行手动的flush操作)
ES会进行默认的flush操作,但同样提供了手动flush的操作;(批量导入大量数据到ElasticSearch的某个索引后,推荐进行手动的flush操作,)
POST /test_index/_flush
在执行flush操作的时候,提供了以下参数:
allow_no_indices | 当索引使用通配符等方式时,是否允许未命中有效索引,该参数设置为true时,未命中索引不会返回错误,反之返回错误 默认为true |
force | 未提交到索引的修改也会被强制刷新(内部参数) 默认为true |
wait_if_ongoing | 如果为true,那么在已有flush请求处理过程中,会阻塞当前flush请求; 如果为flase,发现已有flush请求,直接返回错误 默认为true |
ignore_unavailable | 使用丢失或关闭的索引,则请求返回错误。 默认为false |
三、Merge操作
上面提到过在每个分片中,存储数据的最小单位为segment,也就是说我们搜索数据的时候会去每个shard中的每个segment寻找数据,所以segment过多是灾难的。
当segment过多的时候,会自动寻找非hot时间段进行merge操作;将多个小的segment合并整理为一个segment。
当然你也可以使用force merge进行强制的手动merge操作,但该操作会使索引只读。这是因为在force merge操作期间,Elasticsearch将所有的分段合并成一个更大的分段,并且在此过程中会暂停写入操作,以确保分段的一致性和完整性。
可以在强制合并的时候指定max_num_segments参数,来指定将多个segment合并成最后的一个索引大小;若指定max_num_segments为1,那么segment将会合并为1个segment。
当然从另外一个角度来说,其实merge就是因为多个segment中的数据量过于碎片,换种思想我们可以在setting中增大index-refresh-interval的值,使得内存缓冲区的数据refresh成segement时,拥有更大的单位;但是注意调大index.refresh_interval意味着数据从写入到被索引也就是进入segement的间隔变长,所以不建议对实时搜索需求的索引调整该参数。
ElasticSearch会进行自动的Merge操作,但同样提供了强制Merge的API。
POST /test_index/_forcemerge?max_num_segments = 1
flush | 是否在合并后执行flush操作; 默认为 |
max_num_segments | 合并到的段数。要完全合并索引,请将其设置为1 . |
wait_for_completion | 如果 默认为 |
四、总结
写入数据时,会首先写入到内存缓冲区,并记录相关translog。
内存缓冲区的数据会在index.refresh_interval时间后,自动写入segment中。
过多的segment会触发merge操作,目的旨在整理segment,防止segment过多影响搜索效率。
而flush操作会将segment们落入到磁盘当中,并同时记录提交点,删除旧的translog释放空间;
当然,es提供了手动的refresh操作,手动的flush操作,手动的强制merge操作;
推荐不需要实时搜索的索引,调大index.refresh_interval,节省IO;
推荐在大量数据写入索引后,手动进行调用flush操作,释放translog的空间;
推荐在集群环境良好,节点不易掉线情况时,调大index.translog.sync_interval,即调大tranlog刷盘时间(默认5s,推荐增大至30s);
不推荐频繁的进行手动强制merge操作,该操作使得索引只读;