Elasticsearch整体结构

整体结构说明:
- 在ES Index集群模式下,有多个
Node(节点)组成。每个节点都是ES的实例 - 每个节点有多个
shard(分片),P0,P1,P2是主分片,R0,R1,R2为副本分片 - 每个分片上对应着就是一个
Lucene Index(底层索引文件) Lucene Index是一个统称- 由多个
Segment(段文件,即倒排索引)组成。每个段文件存储的就是Doc文档 Commit Point记录了所有segments的信息Memory Buffer,数据缓冲区TransLog,事务日志
- 由多个
Lucene索引结构

更多文件类型(可参考这里)如下:

文件的关系如下:

Lucene处理流程

创建索引的过程:
- 准备待索引的原文档,数据来源可能是文件、数据库或网络
- 对文档的内容进行分词组件处理,形成一系列的
Term - 索引组件对文档和
Term处理,形成字典和倒排表
搜索索引的过程:
- 对查询语句进行分词处理,形成一系列
Term - 根据倒排索引表查找出包含
Term的文档,并进行合并形成符合结果的文档集 - 比对查询语句与各个文档相关性得分,并按照得分高低返回
文档的写入与删除

文档写入
- 将
Document写入到Memory Buffer(内存缓冲区) - 当满足一定条件后内存缓冲区中的
Documents刷新到高速缓存(Cache),数据从Buffer到Cache的过程是定期每秒刷新一次 - 生成新的
Segment,这个Segment还在Cache中;这时候还没有commit,但是已经可以被读取了
Translog 事务日志
-
Document写入到Memory Buffer时,同时会追加TransLog(类似MySQL中的binlog) -
当
Buffer中的数据每秒Refresh到Cache中时,Translog并没有进入到刷新到磁盘,是持续追加的 -
Translog每隔 5s 会 fsync 到磁盘 -
Translog会继续累加变得越来越大,当Translog大到一定程度或者每隔一段时间,会执行flush
flush 操作会分为以下几步执行:
Buffer被清空- 记录
commit point Cache内的Segment被fsync刷新到磁盘Translog被删除
值得注意的是:
Translog每 5s 刷新一次磁盘,所以故障重启,可能会丢失 5s 的数据Translog执行flush操作,默认 30 分钟一次,或者Translog太大也会执行
删除和更新
Segment 不可改变,所以 Docment 并不能从之前的 Segment 中移除或更新。
所以每次 commit, 生成 commit point 时,会有一个 .del 文件,里面会列出被删除的 Document(逻辑删除)。
而查询时,获取到的结果在返回前会经过 .del 过滤。更新时,也会标记旧的 Docment 被删除,写入到 .del 文件,同时会写入一个新的文件。
此时查询会查询到两个版本的数据,但在返回前会被移除掉一个。
Segment 合并
每 1s 执行一次 Refresh 都会将内存中的数据创建一个 Segment。
Segment 数目太多会带来较大的麻烦。每一个 Segment 都会消耗文件句柄、内存和 cpu 运行周期。
更重要的是,每个搜索请求都必须轮流检查每个 Segment,所以 Segment 越多,搜索也就越慢。
在 ES 后台会有一个线程进行 Segment 合并:
Refresh操作会创建新的Segment并打开以供搜索使用。- 合并进程选择一小部分大小相似的
Segment,并且在后台将它们合并到更大的Segment中。这并不会中断索引和搜索。 - 当合并结束,老的
Segment被删。
说明合并完成时的活动:
- 新的
Segment被刷新(flush)到了磁盘。 写入一个包含新Segment且排除旧的和较小的Segment的新commit point。 - 新的
Segment被打开用来搜索。 - 老的
Segment被删除(物理删除)