Elasticsearch分片、路由、数据写入过程

分片和路由

在Elasticsearch中,若要进行分片和副本配置,则需要尽早配置
因为 当 在一个多分片 的 索引中 写入数据时,需要 通过路由 来确定 具体写入 哪一个分片中
所以 在创建索引时 需要指定 分片的数量,并且分片的数量 一旦确定 就不能修改

分片的数量 和 副本数量 都可以通过 创建索引时的Settings来配置
Elasticsearch默认 为一个索引 创建5个主分片,并分别为 每个分片 创建一个副本
配置的参数如下所示:
在这里插入图片描述
对文档的新建、索引和删除请求等写操作,必须在主分片上面完成之后 才能被复制到 相关的副本分片
Elasticsearch为了加快写入的速度,写入过程往往是并发实施的

为了解决 在并发写的过程中 出现的 数据冲突的问题,Elasticsearch通过乐观锁进行控制,每个文档都有一个version (版本号),当文档被修改时版本号递增

分片如何使用?(和数据写入过程有关)

当向Elasticsearch写入数据时,Elasticsearch 根据 文档标识符ID 将文档 分配到 多个分片上
当查询数据时,Elasticsearch会查询 所有的分片 并 汇总结果
对用户而言,这个过程是透明的,用户并不知道数据到底存在哪个分片上

为了避免在查询时 部分分片 查询失败 影响结果的准确性,Elasticsearch引入了路由功能
即 数据在写入时,通过 路由 将数据 写入 指定分片
在查询时,可以通过 相同的路由 指明 在哪个分片 将数据查出来

在默认情况下,索引数据的分片算法如下所示:
在这里插入图片描述

routing字段的取值 默认是 id字段 或者 是parent字段
routing字段 在Hash分片之后 再与 有分片的数量 取模,最终得到 这条数据 应该被分配在 哪一个分片上

这样做的目的 是通过 Hash分片 来保证 在每个分片上 数据量的 均匀分布,避免 各个分片的存储负载不均衡
在做数据检索时,Elasticsearch默认会搜索 所有分片上的数据,最后 在主节点上 汇总 各个分片数据 并进行 排序处理后,返回最终的结果数据

数据写入过程(重要!!!)

数据写入操作是在Elasticsearch的内存中执行的,数据会被分配到特定的分片和副本上,但最终数据是需要存储到磁盘上持久化的

在Elasticsearch中,数据的存储路径在配置文件../config/elasticsearch.yml中进行设置,具体设置如下:

注:建议不要使用默认值,主要是考虑到当Elasticsearch升级时数据的安全性问题,防止因升级Elasticsearch而导致数据部分甚至全部丢失

1.分段存储

索引数据在磁盘上的 是以 分段形式存储的
“段”是Elasticsearch从Lucene中继承的概念
在索引中,索引文件被拆分为多个子文件,其中每个子文件就叫作段,每个段 都是一个 倒排索引的小单元
段具有不变性,一旦索引的数据被写入硬盘,就不能再修改

为什么要引入分段?

可以试想一下,如果全部的文档集合仅构建在一个很大的倒排索引文件中,且数据量还在不断增加,当进行修改时,需要全量更新当前的倒排索引文件
这会使得数据更新时效性很差、且耗费大量资源

其实在Lucene中,分段的存储模式 可以避免 在读写操作时 使用锁,从而大大提升Elasticsearch的读写性能
这有点类似于CurrentHashMap中“分段锁”的概念,二者有异曲同工之妙,都是为了减少锁的使用,提高并发

当分段被写入磁盘后 会生成 一个提交点,提交点 意味着 一个用来记录 所有段信息的文件 已经生成
因此,一个段 一旦拥有了 提交点,就表示 从此 该段 仅有读的权限,永远失去了写的权限

当段在内存中时,此时分段 拥有 只写的权限,数据还会不断写入,而不具备 读数据的权限,意味着这部分数据 不能被 Elasticsearch用户检索到

既然索引文件分段存储并且不可修改,那么新增、更新和删除如何处理?

新增是比较容易处理的,既然数据是新的,那么只需在当前文档新增一个段即可

删除数据时,由于分段不可修改的特性,Elasticsearch不会把文档 从 旧的段中 移除,而是新增一个.del文件,.del文件中 会记录 这些 被删除文档 的 段信息
被标记删除的文档 仍然可以 被查询匹配到,但它会在 最终结果 被返回前 通过.del文件 将其 从结果集中移除

当更新数据时,由于分段不可修改的特性,Elasticsearch无法通过 修改旧的段 来反映 文档的更新,于是,更新操作 变成了 两个操作的结合,即先删除、后新增
Elasticsearch会将旧的文档从.del文件中标记删除,然后 将文档的新版本 索引到 一个新的段中
在查询数据时,两个版本的文档 都会被 一个查询匹配到,但 被删除的旧版本文档 在结果集返回前 就会被移除

综上所述,段作为不可修改是具有一定优势的,段的优势主要表现在:不需要锁,从而提升Elasticsearch的读写性能

分段不变性的主要缺点 是 存储空间占用量大——当删除旧数据时,旧数据不会被马上删除,而是在.del文件中被标记为删除
而旧数据 只能等到 段更新时 才能被移除,这样就会导致存储空间的浪费
倘若频繁更新数据,则每次更新都是新增新的数据到新分段,并标记旧的分段中的数据,存储空间的浪费会更多

在删除和更新数据时,存储空间会浪费
在检索数据时,依然有局限——在查询得到的结果集中会包含所有的结果集,因此 主节点 需要排除 被标记删除的旧数据,随之带来的是查询的负担

2.延迟写策略

在Elasticsearch中,索引写入磁盘的过程是异步的
为了提升写的性能,Elasticsearch 并没有 每新增一条数据 就 增加一个段 到 磁盘上,而是采用 延迟写策略

延迟写策略的执行过程如下:
每当有新的数据写入时,就将其 先写入 JVM的内存中
在 JVM内存 和 磁盘之间 是 文件系统缓存,文件缓存空间 使用的是 操作系统的空间
当达到默认的时间 或者 JVM内存的数据达到一定量时,会触发一次刷新(Refresh)操作
刷新操作 将 JVM内存中的数据 生成到 一个新的分段上 并缓存到 文件缓存系统,稍后 再被刷新到 磁盘中 并生成 提交点

需要指出的是,由于 新的数据 会继续写入内存,而 JVM内存中的数据 并不是以段的形式 存储的,因此不能提供检索功能
只有当 数据 经由JVM内存 刷新到 文件缓存系统,并生成新的段后,新的段 才能供 搜索使用,而不需要等到 被刷新到 磁盘才可以搜索

在Elasticsearch中,写入和打开一个新段的过程 叫作 刷新
在默认情况下,每个分片 会 每秒自动刷新一次
这就是Elasticsearch能做到近实时搜索的原因,因为 文档的变化 并不是 立即 对搜索可见的,但会在一秒之内变为可见

当然,除自动刷新外,也可以手动触发刷新
还可以在创建索引时,在Settings中通过配置refresh_interval的值,来调整 索引的刷新频率
在设置值时需要注意后面带上时间单位,否则默认是毫秒
refresh_interval=-1时,表示关闭索引的自动刷新

虽然 延迟写策略 可以减少 数据 往 磁盘上写的次数,提升Elasticsearch的整体写入能力,但 文件缓存系统的引入 同时也带来了 数据丢失的风险,如机房断电等
为此,Elasticsearch引入事务日志(Translog)机制
事务日志 用于记录 所有 还没有持持久化到磁盘 的 数据
于是,在添加了事务日志机制后,数据写入索引的流程如下所示:

  1. 新文档 被 索引之后,先被写入 JVM内存中。为了防止数据丢失,Elasticsearch 会 追加一份数据 到 事务日志中
  2. 新的文档 持续在被 写入JVM内存时,同时 也会记录到 事务日志中。当然,此时的新数据 还不能被检索和查询
  3. 当 达到 默认的刷新时间 或 JVM内存中的数据达到一定量后,Elasticsearch会触发一次刷新,将JVM内存中的数据 以一个新段形式 刷新到 文件缓存系统中 并 清空JVM内存。这时新段虽未被提交到磁盘,但已经可以对外提供文档的检索功能 且 不被修改
  4. 随着 新文档索引 不断被写入,当日志数据大小超过某个值,或者超过一定时间时,Elasticsearch会触发一次Flush
    此时,JVM内存中的数据 被写入 一个新段,同时被写入 文件缓存系统,文件缓存系统中的数据 通过Fsync刷新到磁盘中,生成提交点。而日志文件被删除,创建一个空的新日志

3.段合并

在Elasticsearch自动刷新流程中,每秒都会创建一个新的段
这自然会导致短时间内段的数量猛增,而当段数量太多时会带来较大的资源消耗,如对文件句柄、内存和CPU的消耗
而在内容搜索阶段,由于搜索请求要检查到每个段,然后合并查询结果,因此段越多,搜索速度越慢

为此,Elasticsearch引入段合并机制
段合并机制在后台定期进行,从而小的段被合并到大的段,然后这些大的段再被合并到更大的段

在段合并过程中,Elasticsearch会将那些 旧的已删除文档 从文件系统中 清除
被删除的文档 不会被 拷贝到新的大段中,当然,在合并的过程中不会中断索引和搜索

段合并 是 自动进行索引和搜索的,在合并进程中,会选择一小部分大小相似的段,在后台将它们合并到更大的段中,这些段既可以是未提交的,也可以是已提交的

在合并结束后,老的段会被删除,新的段被Flush到磁盘,同时 写入一个 包含新段 且 排除旧的 和 较小的段 的 新提交点。打开新的段之后,可以用来搜索。

由于段合并的计算量较大,对磁盘I/O的消耗也较大,因此 段合并 会影响 正常的数据写入速率,因此Elasticsearch不会放任自流,让段合并影响搜索性能
Elasticsearch在默认情况下 会对 合并流程 进行 资源限制,这就是搜索服务仍然有足够的资源仍然可以执行的原因

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值