Generic placeholder image
闲敲代码、落灯花
What's past is prologue

联系邮箱:email@hezehua.net


联系QQ:1907330840

座右铭

保持热情,持续学习,每日精进

Elasticsearch 数据写入原理

Elasticsearch 数据写入原理

本文与作者在csdn上的博文【Elasticsearch 数据写入原理】保持同步


1、elasticsearch 如何使文档可以被搜索

为了支持全文检索而采用倒排索引,倒排索引包含一个有序列表,列表包含所有文档出现过的词项 ,对于每一个词项,包含了它所有曾出现过文档的列表。
早期的倒排索引,会在文档变化时,重建新的索引,直到完成后替换掉旧的索引,这样新的变化就可以被搜索到。
倒排索引具有不变性,这使得索引一旦被读入文件系统缓存,便会留在那里,只要有足够的空间,就可以使大部分请求直接命中缓存,很大地提升了性能,缺点是,如果有新的文档需要被搜索,只能重建整个索引。

2、如何使用更好的方式实现倒排索引的更新

上面说了,由于索引的不变性,更新索引的方式是重建整个索引,这种方式对于数据量和更新频率的情况是有很大限制的,所以elasticsearch通过增加新的补充索引来反映新近的修改,而不是直接重写整个倒排索引。最终通过轮询每一个倒排索引并对结果进行合并才创建新的索引。

  • 按段搜索
    elasticsearch 基于lucene 引入了 按段搜索的概念,每一个段,都是一个倒排索引,而一个Lucene索引,除了包含多个段之外,还包含commit point、.liv文件。
    其中,commit point记录了每一次的创建新段,当一个段存在文档被删除,会维护该信息在 .liv 文件里面。

逐段搜索会以如下流程进行工作:

  1. 新增的文档写入内存缓存
  2. 每隔一段时间,创建一个新段,将文档从内存缓存中被提交到新段
  3. 新段写入到磁盘(文件系统缓存)
  4. 新的commit point 也 写入到磁盘(文件系统缓存)
  5. 磁盘 fsync ,从文件系统缓存中价格写入操作同步到物理磁盘
  6. 这个新的段被开启, 使得段内文档对搜索可见
  7. 清空内存缓存,继续接受新的文档

3、如何实现近实时搜索

上面的写入到可检索过程,主要瓶颈在磁盘fync,大量文档需要写入磁盘可能造成很明显的延迟,而且每次的索引一个文档都要做磁盘fsync会造成性能问题。所以elasticsearch更轻量的方式来使一个文档可被搜索——将fsync从【写入到可检索】的步骤中移除——在新段写入文件系统缓存之后就可检索。
在第1部分中描述了倒排索引在文件系统缓存中被请求,所以在新段写入文件系统缓存之后就可以被打开和读取了。写入文件系统缓存和打开新段被称为refresh,默认情况下每秒进行一次refresh,也可以更改该项设置,或者手动执行。
有了refresh之后,索引文档的步骤更改为:

  1. 新增的文档写入内存缓存
  2. 每隔一段时间,创建一个新段,refresh,此时新段可被检索
  3. 通过fsync刷新磁盘(flush) ,从文件系统缓存中将所有写入操作同步到物理磁盘
  4. 清空内存缓存,继续接受新的文档

4、数据持久化

上面说到新段先写入文件系统缓存,再fsync到磁盘,在这个过程中,如果断电,则无法将未来得及同步的数据持久化到磁盘,所以elasticsearch 增加了一个 translog,也叫事务日志,记录了每一次的操作。

  1. 在文档写入内存缓存的同时,写入到translog中
  2. 执行refresh时,会清空内存缓存,且没有fsync到磁盘时,translog仍然保留
  3. 每隔一段时间或者translog文件太大,索引被刷新,所有在内存缓冲区的文档都被写入一个新的段,清空内存缓存,一个提交点被写入硬盘,新的traslog文件被创建,旧的被删除

而在执行refresh后,fsync之前,如果重启elasticsearch,它会从磁盘中使用最后一个提交点去恢复已知的段,并且会重放 translog 中所有在最后一次提交后发生的变更操作。

5、段合并

由于在自动刷新流程每秒会创建一个新的段,段时间内就会积累大量的段,每一个段都会消耗文件句柄、内存和cpu运行周期,而且在检索时需要遍历所有段来查找文档,这样无疑是一个巨大的性能瓶颈。elasticsearch通过在后台进行段合并来解决这个问题,小的段被合并到大的段,然后这些大的段再被合并到更大的段,段合并的时候会将那些旧的已删除文档从文件系统中清除。
段合并不会中断检索和索引的过程,在索引的时候,创建新段,段合并就会自动执行,合并的段将继续执行之后的步骤。
手动进行强制段合并可使用optimize api,它会将一个分片强制合并到 max_num_segments 个段,但该操作可能会无限制的使用资源,造成集群内短时间内无法响应。

猜你喜欢
Elasticsearch 搜索数组字段
阅读 574

1、搜索 数组字段 tags 中同时存在元素 str_a、str_b{ "query": { "bool": { "filter": [ { "term":...

Elasticsearch实战:给博客打造全文检索
阅读 116

学习和使用Elasticsearch有一段时间了,项目中大量使用到了es,但对于我来说都是部分或者局部地去使用,所以得找个时间好好整理并且再完整时实践一下es,于是就有了这篇文章,本文将先简单介绍一下使用到的相关技术,然后再整体讲解实战内容。首先系统架构是LNMP,很简单的个人博客网站(逐步前...

Elasticsearch 模糊搜索
阅读 343

Es 实现类似于mysql的模糊搜索: 比如:对字段 keywords 进行 模糊搜索 带“愉”字的文档: { "query": { "bool": { "filter": [ { ...

Elasticsearch 定制评分(自定义评分)
阅读 91

Elasticsearch 的相似度算法被定义为检索词频率/反向文档频率, TF/IDF 。一. 相关概念:检索词频率:tf词 t 在文档 d 的词频( tf )是该词在文档中出现次数的平方根。tf(t in d) = √frequency检索词在该字段出现的频率?出现频率越高,相关...

elasticsearch 去重计数
阅读 102

去重计数不是精确计数,数据量大的情况下会有误差,官方文档说的是,默认的情况下百万级数据会有5%的误差,实测如下: 实际文档数:1924920 去重计数:1912715 误差率:(1924920 - 1912715)/ 1924920 = 0.006 %0.6的误差率还能接受,如果需要更高的准确...

记一次ElasticSearch 更改 mapping 字段类型的过程
阅读 648

首先,es不支持直接跟那个该mappinng,所以,更改 mapping 实质上是重建索引。 操作步骤如下: 1、为当前这个索引old_index设置一个别名my_index: curl -XPOST localhost:9200/_aliases -d ' { "act...

elasticsearch查询文档数量
阅读 145

查询文档数量时很常见的操作,一般可以直接使用count获取文档数,但是获取到数量信息,在【分页】应用中,意味着需要查询分页然后再查询总数。 有另一种方法,可以让我们在一次查询中获取分页数据并得到总量。 在搜索时,结果中的 hits.total 信息中会包含一个整数值表示文档数,当实际文档数小于10...