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
被删除(物理删除)