乐趣区

关于java:Elasticsearch-技术分享-十张图带大家看懂-ES-原理-明白为什么说ES-是准实时的

前言

说到 Elasticsearch,其中最显著的一个特点就是 near real-time 准实时 —— 当文档存储在 Elasticsearch 中时,将在 1 秒内以简直实时的形式对其进行索引和齐全搜寻。那为什么说 ES 是准实时的呢?

公众号:『刘志航』,记录工作学习中的技术、开发及源码笔记;时不时分享一些生存中的见闻感悟。欢送大佬来领导!

Lucene 和 ES

Lucene

Lucene 是 Elasticsearch 所基于的 Java 库,它引入了按段搜寻的概念。

Segment:也叫段,相似于倒排索引,相当于一个数据集。

Commit point:提交点,记录着所有已知的段。

Lucene index:“a collection of segments plus a commit point”。由一堆 Segment 的汇合加上一个提交点组成。

对于一个 Lucene index 的组成,如下图所示。

Elasticsearch

一个 Elasticsearch Index 由一个或者多个 shard(分片)组成。

而 Lucene 中的 Lucene index 相当于 ES 的一个 shard。

写入过程

写入过程 1.0(不欠缺)

  1. 一直将 Document 写入到 In-memory buffer(内存缓冲区)。
  2. 当满足肯定条件后内存缓冲区中的 Documents 刷新到磁盘。
  3. 生成新的 segment 以及一个 Commit point 提交点。
  4. 这个 segment 就能够像其余 segment 一样被读取了。

画图如下:

将文件刷新到磁盘是十分消耗资源的,而且在内存缓冲区和磁盘两头存在一个高速缓存(cache),一旦文件进入到 cache 就能够像磁盘上的 segment 一样被读取了。

写入过程 2.0

  1. 一直将 Document 写入到 In-memory buffer(内存缓冲区)。
  2. 当满足肯定条件后内存缓冲区中的 Documents 刷新到 高速缓存(cache)。
  3. 生成新的 segment,这个 segment 还在 cache 中。
  4. 这时候还没有 commit,然而曾经能够被读取了。

画图如下:

数据从 buffer 到 cache 的过程是定期每秒刷新一次。所以新写入的 Document 最慢 1 秒就能够在 cache 中被搜寻到。

而 Document 从 buffer 到 cache 的过程叫做 ?refresh。个别是 1 秒刷新一次,不须要进行额定批改。当然,如果有批改的须要,能够参考文末的相干材料。这也就是为什么说 Elasticsearch 是 准实时 的。

使文档立刻可见:

PUT /test/_doc/1?refresh
{"test": "test"}

// 或者
PUT /test/_doc/2?refresh=true
{"test": "test"}

Translog 事务日志

此处能够联想 Mysql 的 binlog,ES 中也存在一个 translog 用来失败复原。

  1. Document 一直写入到 In-memory buffer,此时也会追加 translog。
  2. 当 buffer 中的数据每秒 refresh 到 cache 中时,translog 并没有进入到刷新到磁盘,是继续追加的。
  3. translog 每隔 5s 会 fsync 到磁盘。
  4. translog 会持续累加变得越来越大,当 translog 大到肯定水平或者每隔一段时间,会执行 flush。

flush 操作会分为以下几步执行:

  1. buffer 被清空。
  2. 记录 commit point。
  3. cache 内的 segment 被 fsync 刷新到磁盘。
  4. translog 被删除。

值得注意的是:

  1. translog 每 5s 刷新一次磁盘,所以故障重启,可能会失落 5s 的数据。
  2. translog 执行 flush 操作,默认 30 分钟一次,或者 translog 太大 也会执行。

手动执行 flush:

POST /my-index-000001/_flush

删除和更新

segment 不可扭转,所以 docment 并不能从之前的 segment 中移除或更新。

所以每次 commit,生成 commit point 时,会有一个 .del 文件,外面会列出被删除的 document(逻辑删除)。
而查问时,获取到的后果在返回前会通过 .del 过滤。

更新时,也会标记旧的 docment 被删除,写入到 .del 文件,同时会写入一个新的文件。此时查问会查问到两个版本的数据,但在返回前会被移除掉一个。

segment 合并

每 1s 执行一次 refresh 都会将内存中的数据创立一个 segment。

segment 数目太多会带来较大的麻烦。每一个 segment 都会耗费文件句柄、内存和 cpu 运行周期。更重要的是,每个搜寻申请都必须轮流查看每个 segment;所以 segment 越多,搜寻也就越慢。

在 ES 后盾会有一个线程进行 segment 合并。

  1. refresh 操作会创立新的 segment 并关上以供搜寻应用。
  2. 合并过程抉择一小部分大小类似的 segment,并且在后盾将它们合并到更大的 segment 中。这并不会中断索引和搜寻。
  3. 当合并完结,老的 segment 被删除 阐明合并实现时的流动:

    1. 新的 segment 被刷新(flush)到了磁盘。写入一个蕴含新 segment 且排除旧的和较小的 segment 的新 commit point。
    2. 新的 segment 被关上用来搜寻。
    3. 老的 segment 被删除。

物理删除:

在 segment merge 这块,那些被逻辑删除的 document 才会被真正的物理删除。

总结

次要介绍了外部写入和删除的过程,须要理解 refresh、fsync、flush、.del、segment merge 等名词的具体含意。

残缺画图如下:

以上就是集体分享的 ES 相干的内容,次要目标是组内技术分享,进行扫盲。不对之处,心愿大家留言斧正。

相干材料

  1. 准实时搜寻:https://www.elastic.co/guide/…
  2. Refresh API:https://www.elastic.co/guide/…
  3. Flush API:https://www.elastic.co/guide/…
退出移动版