0%

elasticsearch过程分析

elasticsearch过程分析

写到哪个分片?

写索引是只能写在主分片上,然后同步到副本。那么如何确定写到哪个分片呢?这个在分片那篇文章中也有提到shard = hash(routing) % number_of_primary_shards

routing默认是文档的_id,也可以自定义

索引文档

当用户向一个节点提交了一个创建文档的请求,节点会计算文档应该加入到哪个分片中,每个节点都存储了每个分片存储在哪个节点的信息,因此协调节点会将请求发送到对应的节点,当主分片完成索引,会将请求发送到所有的副本,保持每个分片的数据都是最新的

每次写入新文档时,都会先写到内存中,然后将这一操作写入translog文件中,此时如果执行搜索,是无法索引到对应文档的。elasticsearch会每隔一段时间进行一次刷新操作,此时内存中的文档会被写入file system cache中,并构成一个segment,此时segment内的文档可以被搜索到,但是还未写入磁盘,如果发生断电,这些文档仍可能丢失。

为了避免丢失数据,会将没有持久化到磁盘的数据写入到事务日志记录,translog文件中

分段存储

索引文档拆分为多个子文件,每个子文件叫做段segment,存在磁盘上。每个段本身就是一个倒排索引,且段一旦被写入磁盘,就不可再修改。由于分段,可以使得在读写时减少锁的出现,提升了并发度

有没有联想到JDK7中ConcurrentHashMap的实现

段在内存中的时候只可写,不可读;在磁盘中的时候,只可读,不可写。那么对于文档的新增、修改、删除是如何处理的?

  • 新增 新增数据肯定就是新增段了,也不需要处理之前的段
  • 删除 由于段已经写入磁盘了,不可以修改,所以通过新增一个.del文件,记录被删除文档的段信息,这些被标记为删除的文档仍然可以被查询匹配到,只是在最终结果返回之前从结果集中移除
  • 修改 由于段已经写入磁盘了,不可以修改,那么修改操作就是上述的删除+新增,其有一个版本的概念,在.del文件中标记该版本删除,被在一个新的段中写入一个新的文档版本

被标记为删除的数据会在段合并中真正被删除掉

刷新周期(refresh 操作)

elasticsearch数据写入后不会被马上搜索到,所以是准实时搜索。

elasticsearch数据写入后会将数据写入到memory buffer中,并将这一操作写入translog中。此时数据是不能被搜索到的。而如果直接将memory buffer中的数据写入到磁盘的话,就需要频繁的IO,会严重降低elasticsearch的性能。

elasticsearch在memory buffer和磁盘之间加入了一层页面高速缓存(File system cache),经过index.refresh_interval时间会将memory buffer的数据refresh到File system cache中,并清空memory buffer,refresh到File system cache中就会生成新的段,此时写入的数据就可以读取到了。

memory buffer使用的elasticSearch的JVM内存,而File system cache使用的是操作系统的内存

这里的refresh的间隔使用refresh_interval来设置,对于实时性要求不高的系统来说,可以设置为30s。如果想要关闭索引的自动刷新,可以设置为-1。

translog也不是实时写入的,默认是每隔5s将数据刷新到磁盘中

1
2
3
4
5
6
"index": {
"translog": {
"sync_interval": "5s",
"durability": "async"
}
}

写入磁盘(flush操作)

File system cache依然是在内存中,为了保证持久性,还是需要flush到磁盘。

当缓存满的时候会触发从File system cache刷到磁盘

1
2
3
4
# 设置缓冲区内存为堆内存的20%
indices.memory.index_buffer_size: 20%
# 设置缓冲区内存最小为96m
indices.memory.min_index_buffer_size: 96mb

translog的作用就是如果机器宕机,内存中的数据会消失,此时重启的时候会读取translog日志文件中的数据,恢复到buffer和file system cache中。

数据flush到磁盘之后translog会清空,再次生成一个新的translog

段合并

随着越来越多的文档写入,将会生成很多的segment,segment过多也会导致查询性能的下降,所以elasticsearch会自动的进行segment的合并

好处

  • 当一些索引段合并为一个索引段的时候,会减少索引段的数量并提高搜索速度
  • 段合并时会移除被标记为已删除的那些文档,所以也会减少索引的容量

欢迎关注我的其它发布渠道