前言
在分布式日志服务架构中,我们只需要将logstash的output指向ES就可以了,但是,写入的数据是如何变成Elasticsearch里可以被检索和聚合的索引内容的呢?本文重点介绍数据在写入Elasticsearch索引流程中发生的具体操作。重点在于其中segment、buffer和translog三部分对实时性和性能方面的影响。
动态更新的Lucene索引
Lucene对于新收到的数据写入到新的索引文件里。Lucene把每次生成的倒排索引,叫做一个segment,然后另外使用一个commit文件,记录索引内所有的segment。而生成segment的数据来源则是放在内存中的buffer,也就是说,动态更新过程如下:
- 当前索引有3个segment可用;
- 新接收的数据进入内存buffer;
- 内存buffer刷到磁盘,生成一个新的segment,commit文件同步更新。
利用磁盘缓存实现的准实时检索
上面的内容中,内存buffer刷入磁盘,但是不可避免的问题就是写磁盘太慢了。对于我们的日志服务来说,如果要进行一些实时性统计,这个速度是不能接受的。所以,在内存buffer刷入磁盘的处理中,还有一个中间状态:
- 内存buffer生成一个新的segment,刷到文件系统缓存中,Lucene即可检索这个新的segment。
- 文件系统缓存真正同步到磁盘上,commit文件更新。
其实就是多加了一步文件系统缓存。Elasticsearch中默认1s中刷新一次。如果觉得间隔时间还是很短,可以调用/_refresh接口来修改。
不过对于日志场景来说,我们更需要的是更快的写入性能,所以我们最好是通过/_settings接口或者定制template的方式,加大refresh_intereval参数:
curl -XPOST http://127.0.0.1:9200/logstash-lms-2019.02.19/_settings -d'{"refresh_interval":"10s"}'
如果是导入历史数据的场合,甚至可以直接关闭。
索引数据一致性保证——translog提供的磁盘同步控制
refres只是写到文件系统缓存,如果最后一步写入到磁盘期间发生了错误、硬件故障灯问题,数据会丢失吗?
这里有另一个控制机制。Elasticsearch在把数据写入到内存buffer的同时,其实还另外记录了一个translog日志。
refres发生时,translog日志文件依旧保持原样。如果期间发生异常,Elasticsearch会从commit位置开始,恢复整个translog文件中的记录,保证数据一致性。
等到真正吧segment刷新到磁盘,commit文件更新后,translog才会清空,即flush操作。
Elasticsearch默认30分钟flush一次,或者translog文件>512M时会主动flush。可以通过以下参数进行设置:
index.translog.flush_threshold_period
index.translog.flush_threshold_size
#控制每收到多少条数据后flush一次
index.translog.flush_threshold_ops
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。