由于在 ES 集群中每个节点通过上面的计算公式都知道集群中的文档的存放位置,所以每个节点都有处理读写请求的能力 。
在一个写请求被发送到某个节点后,该节点即为前面说过的协调节点,协调节点会根据路由公式计算出需要写到哪个分片上,再将请求转发到该分片的主分片节点上 。

文章插图
假如此时数据通过路由计算公式取余后得到的值是
shard=hash(routing)%4=0 。则具体流程如下:
- 客户端向 ES1 节点(协调节点)发送写请求,通过路由计算公式得到值为 0,则当前数据应被写到主分片 S0 上 。
- ES1 节点将请求转发到 S0 主分片所在的节点 ES3,ES3 接受请求并写入到磁盘 。
- 并发将数据复制到两个副本分片 R0 上,其中通过乐观并发控制数据的冲突 。一旦所有的副本分片都报告成功,则节点 ES3 将向协调节点报告成功,协调节点向客户端报告成功 。
存储原理上面介绍了在 ES 内部索引的写处理流程,这个流程是在 ES 的内存中执行的,数据被分配到特定的分片和副本上之后,最终是存储到磁盘上的,这样在断电的时候就不会丢失数据 。
具体的存储路径可在配置文件
../config/elasticsearch.yml 中进行设置,默认存储在安装目录的 Data 文件夹下 。建议不要使用默认值,因为若 ES 进行了升级,则有可能导致数据全部丢失:
path.data: /path/to/data //索引数据 path.logs: /path/to/logs //日志记录 ①分段存储索引文档以段的形式存储在磁盘上,何为段?索引文件被拆分为多个子文件,则每个子文件叫作段,每一个段本身都是一个倒排索引,并且段具有不变性,一旦索引的数据被写入硬盘,就不可再修改 。
在底层采用了分段的存储模式,使它在读写时几乎完全避免了锁的出现,大大提升了读写性能 。
段被写入到磁盘后会生成一个提交点,提交点是一个用来记录所有提交后段信息的文件 。
一个段一旦拥有了提交点,就说明这个段只有读的权限,失去了写的权限 。相反,当段在内存中时,就只有写的权限,而不具备读数据的权限,意味着不能被检索 。
段的概念提出主要是因为:在早期全文检索中为整个文档集合建立了一个很大的倒排索引,并将其写入磁盘中 。
如果索引有更新,就需要重新全量创建一个索引来替换原来的索引 。这种方式在数据量很大时效率很低,并且由于创建一次索引的成本很高,所以对数据的更新不能过于频繁,也就不能保证时效性 。
索引文件分段存储并且不可修改,那么新增、更新和删除如何处理呢?
- 新增,新增很好处理,由于数据是新的,所以只需要对当前文档新增一个段就可以了 。
- 删除,由于不可修改,所以对于删除操作,不会把文档从旧的段中移除而是通过新增一个 .del 文件,文件中会列出这些被删除文档的段信息 。这个被标记删除的文档仍然可以被查询匹配到,但它会在最终结果被返回前从结果集中移除 。
- 更新,不能修改旧的段来进行反映文档的更新,其实更新相当于是删除和新增这两个动作组成 。会将旧的文档在 .del 文件中标记删除,然后文档的新版本被索引到一个新的段中 。可能两个版本的文档都会被一个查询匹配到,但被删除的那个旧版本文档在结果集返回前就会被移除 。
- 不需要锁 。如果你从来不更新索引,你就不需要担心多进程同时修改数据的问题 。
- 一旦索引被读入内核的文件系统缓存,便会留在哪里,由于其不变性 。只要文件系统缓存中还有足够的空间,那么大部分读请求会直接请求内存,而不会命中磁盘 。这提供了很大的性能提升 。
- 其它缓存(像 Filter 缓存),在索引的生命周期内始终有效 。它们不需要在每次数据改变时被重建,因为数据不会变化 。
- 写入单个大的倒排索引允许数据被压缩,减少磁盘 I/O 和需要被缓存到内存的索引的使用量 。
- 当对旧数据进行删除时,旧数据不会马上被删除,而是在 .del 文件中被标记为删除 。而旧数据只能等到段更新时才能被移除,这样会造成大量的空间浪费 。
推荐阅读
- 远安黄茶功效禁忌,黄茶的功效与作用及禁忌详解
- 黄茶都有哪几种,详解黄茶和绿茶的区别
- 黄茶的保健功效与作用,黄茶的功效与作用及禁忌详解
- 岳阳黄茶品质特点,详解黄茶特点
- 黄茶的保健功能,黄茶的功效与作用及禁忌详解
- 黄茶具备的品质特点,详解黄茶特点
- 青茶红茶黑茶白茶绿茶黄茶等都有什么区别,详解黄茶和绿茶的区别
- 虎山黄茶的功效与作用及禁忌,黄茶的功效与作用及禁忌详解
- 黄小茶品质特点,详解黄茶特点
- 黄茶的特点与功效及禁忌,黄茶的功效与作用及禁忌详解
