说到 Elasticsearch,张图其中最明显的说清一个特点就是 near real-time 准实时,当文档存储在 Elasticsearch 中时,张图将在 1 秒内以几乎实时的说清方式对其进行索引和完全搜索。那为什么说 ES 是张图准实时的呢? Lucene 和 ES Lucene Lucene 是 Elasticsearch所基于的 Java 库,它引入了按段搜索的说清概念: 对于一个 Lucene index 的张图组成,如下图所示: ES 一个 Elasticsearch Index 由一个或者多个 shard(分片)组成。说清 而 Lucene 中的张图 Lucene index 相当于 ES 的一个 shard。 写入过程 写入过程 1.0(不完善) 写入过程 1.0 如下: 画图如下: 将文件刷新到磁盘是非常耗费资源的,而且在内存缓冲区和磁盘中间存在一个高速缓存(cache),一旦文件进入到 cache 就可以像磁盘上的 segment 一样被读取了。 写入过程 2.0 写入过程 2.0 如下: 画图如下: 数据从 buffer 到 cache 的过程是定期每秒刷新一次。所以新写入的 Document 最慢 1 秒就可以在 cache 中被搜索到。 而 Document 从 buffer 到 cache 的过程叫做 ?refresh。一般是 1 秒刷新一次,不需要进行额外修改。 当然,如果有修改的需要,可以参考文末的相关资料。这也就是为什么说 Elasticsearch 是准实时的源码库。 使文档立即可见: Translog 事务日志 此处可以联想 MySQL 的 binlog,ES 中也存在一个 translog 用来失败恢复: flush 操作会分为以下几步执行: 值得注意的是: 手动执行 flush: 删除和更新 segment 不可改变,所以 docment 并不能从之前的 segment 中移除或更新。 所以每次 commit,站群服务器 生成 commit point 时,会有一个 .del 文件,里面会列出被删除的 document(逻辑删除)。 而查询时,获取到的结果在返回前会经过 .del 过滤。更新时,也会标记旧的 docment 被删除,写入到 .del 文件,同时会写入一个新的文件。 此时查询会查询到两个版本的数据,但在返回前会被移除掉一个。 segment 合并 每 1s 执行一次 refresh 都会将内存中的数据创建一个 segment。 segment 数目太多会带来较大的麻烦。每一个 segment 都会消耗文件句柄、内存和 cpu 运行周期。 更重要的是,每个搜索请求都必须轮流检查每个 segment ;所以 segment 越多,搜索也就越慢。 在 ES 后台会有一个线程进行 segment 合并: 说明合并完成时的活动: 物理删除:在 segment merge 这块,那些被逻辑删除的 document 才会被真正的物理删除。 总结 主要介绍了内部写入和删除的过程,需要了解 refresh、fsync、flush、.del、segment merge 等名词的具体含义。 完整画图如下: 以上就是个人分享的 ES 相关的内容,主要目的是组内技术分享,进行扫盲。不对之处,希望大家留言指正。 相关资料: https://www.elastic.co/guide/en/elasticsearch/reference/7.9/near-real-time.html https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-refresh.html https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-flush.html 作者:刘志航 编辑:陶家龙 出处:转载自公众号刘志航(ID:liuzhihangs)图片来自 Pexels