Elasticsearch系列---shard内部原理

概要

本篇我们来看看shard内部的一些操作原理,了解一下人家是怎么玩的。

倒排索引

倒排索引的结构,是非常适合用来做搜索的,Elasticsearch会为索引的每个index为analyzed的字段建立倒排索引。

基本结构

倒排索引包含以下几个部分:

  • 某个关键词的doc list
  • 某个关键词的所有doc的数量IDF(inverse document frequency)
  • 某个关键词在每个doc中出现的次数:TF(term frequency)
  • 某个关键词在这个doc中的次序
  • 每个doc的长度:length norm
  • 某个关键词的所有doc的平均长度

记录这些信息,就是为了方便搜索的效率和_score分值的计算。

不可变性

倒排索引写入磁盘后就是不可变的,这样有几个好处:

  1. 不需要锁,如果不更新索引,不用担心锁的问题,可以支持较高的并发能力
  2. 如果cache内存足够,不更新索引的话,索引可以一直保存在os cache中,可以提升IO性能。
  3. 如果数据不变,filter cache会一直驻留在内存。
  4. 索引数据可以压缩,节省cpu和io开销。

doc底层原理

前面提到倒排索引是基于不可变模式设计的,但实际Elasticsearch源源不断地有新数据进来,那光是建立、删除倒排索引,岂不是非常忙?

如果真是不停地建立,删除倒排索引,那ES压力也太大了,肯定不是这么实现的。ES通过增加新的补充索引来接收新的文档和修改的文档,而不是直接用删除重建的方式重写整个索引。

doc写入

整个写入过程如下图所示:

  1. 新文档先写入内存索引缓存
  2. 当间隔一定时间(1秒),将缓存的数据进行提交,这个过程会创建一个Commit Point,Commit Point包含index segment的信息。
  3. 缓存的数据写入新的index segment。
  4. index segment的数据先写入os-cache中
  5. 等待操作系统将os-cache的数据强制刷新到磁盘中
  6. 写入磁盘完成后,新的index segment被打开,此时segment内的文档可以被搜索到。
  7. 同时buffer的数据被清空,等待下一次新的文档写入。

index segment翻译过来叫"段",每秒会创建一个,ES把这个1秒内收到的、需要处理的文档都放在这个段里,可以把段认为是倒排索引的一个子集。

索引、分片、段的关系如下:
索引包含多个分片,每个分片是一个Lucene索引实例,一个分片下面有多个段。如果把分片看作是一个独立的倒排索引结构,那么这个倒排索引是由多个段文件的集合。
三者之间是包含关系:索引包含多个分片,分片包含多个段。

doc删除和更新

当文档被删除时,Commit Point会把信息记录在.del文件中,在.del文件中会标识哪些文档是有deleted标记的,但该文档还是存在于原先的index segment文件里,同样能够被检索到,只是在最终结果处理时,标记为deleted的文档被会过滤掉。

更新也是类似的操作,更新会把旧版本的文档标记为deleted,新的文档会存储在新的index segment中。

近实时搜索

上面的流程细节的童鞋可以会发现,每次都需要fsync磁盘,数据才是可搜索的,那IO压力将特别大,耗费时间比较长,并且执行周期由操作系统控制,从一个新文档写入到可以被搜索,超过1分钟那是常有的事。

所以Elasticsearch对此做了一个改进:
index segment信息写入到os-cache中,即完成上面的第4步,该segment内的文档信息就可以被搜索到了。fsync操作就不立即执行了,

os-cache的写入代价比较低,最耗时的fsync操作交由操作系统调度执行。

上述的index segment写入到os-cache,并打开搜索的过程,叫做refresh,默认是每隔1秒refresh一次所以,es是近实时的,数据写入到可以被搜索,默认是1秒。

refresh的时间也可以设置,比如我们一些日志系统,数据量特别大,但实时性要求不高,我们为了优化资源分配,就可以把refresh设置得大一些:

PUT /music
{
  "settings": {
    "refresh_interval": "30s"
  }
}

此参数需要在创建索引时使用,要注意一下的是除非有充分的依据,才会对refresh进行设置,一般使用默认的即可。

translog机制

上述的写入流程当中,如果fsync到磁盘的操作没执行完成,服务器断电宕机了,可能会导致Elasticsearch数据丢失。Elasticsearch也设计了translog机制,跟关系型数据库的事务日志机制非常像,整个写入过程将变成这样:

  1. 新文档写入内存buffer的同时,也写一份到translog当中。
  2. 内存buffer的数据每隔1秒写入到index segment,并写入os-cache,完成refresh操作。
  3. 内存buffer被清空,但translog一直累加。
  4. 每隔5秒translog信息fsync到磁盘上。
  5. 默认每30分钟或translog累积到512MB时,执行全量commit操作,os-cache中的segment信息和translog信息fsync到磁盘中,持久化完成。
  6. 生成新的translog,旧的translog归档(6.x版本translog做归档操作,不删除)。

flush API

这个执行一个提交并且归档translog的行为称作一次flush。分片每30分钟被自动刷新(flush),或者在 translog 太大的时候(默认512MB)也会刷新,当然也可以手动触发flush的执行,如下请求:

POST /music/_flush

但任其自动flush就够了。如果重启节点前担心会对索引造成影响,可以手动flush一下。毕竟节点重启后需要从translog里恢复数据,translog越小,恢复就越快。

durability同步和异步

translog写磁盘行为主要有两种,是由index.translog.durability配置项决定的:

  • request:同步写磁盘,每次写请求完成之后立即执行(新增、删除、更新文档),以及primary shard和replica shard同步都会触发,数据安全有保障,不丢失,但会带来一些性能损失。如果是bulk数据导入,每个文档平摊下来的损失是比较小的。
  • async:异步写磁盘,默认5秒fsync一次,如果有宕机事件,可能会丢失几秒的数据,适用于允许偶尔有数据丢失的场景,如日志系统。

如果系统不接受数据丢失,用translog同步方式,示例设置:

# 异步方式
PUT /music_new
{
  "settings": {
    "index.translog.durability": "async",
    "index.translog.sync_interval": "5s"
  }
}

# 同步方式
PUT /music_new
{
  "settings": {
    "index.translog.durability": "request"
  }
}

segment合并

Elasticsearch针对活跃的索引,每秒都会生成一个新的index segment,这些segment最终会以文件的形式存储在磁盘里,如果不对其进行处理,那么索引运用一段时间后,会有特别多的文件,零碎的文件太多了,也不是什么好事情,更耗费更多的文件资源,句柄等,搜索过程也会变慢。

合并过程

Elasticsearch会在后台对segment进行合并,减少文件的数量,同时,标记为deleted的文档在合并时会被丢弃(delete请求只是将文档标记为deleted状态,真正的物理删除是在段合并的过程中),合并过程不需要人工干预,让Elasticsearch自行完成即可。

两个已经提交的段和一个未提交的段合并成为一个大的段文件

合并时会挑一些大小接近的段,合并到更大的段中,段合并过程不阻塞索引和搜索。

合并完成后,新的更大的段flush到磁盘中,并完成refresh操作,老的段被删除掉。

optimize API

optimize命令可以强制合并API,并指定最终段的数量,如下命令:

POST /music_new/optimize
{
  "max_num_segments": 1
}

指定segment最大数量为1,表示该索引最终只有一个segment文件。

适用场景
  1. 正常活跃的、经常有更新的索引不建议使用
  2. 日志类的索引,对老数据进行优化时,可以将每个分片的段进行合并
使用建议
  1. 一般不需要人工干预合并过程
  2. optimize操作会消耗大量的IO资源,使用要慎重考虑

小结

本篇主要介绍shard内部的原理,包含写入、更新删除,translog机制,segment合并等,了解数据库的童鞋对translog机制应该非常熟悉,原理上大同小异,仅作抛砖引玉,谢谢。

原文地址:https://www.cnblogs.com/huangying2124/p/12230177.html

时间: 2024-11-09 07:23:49

Elasticsearch系列---shard内部原理的相关文章

Elasticsearch系列---增量更新原理及优势

概要 本篇主要介绍增量更新(partial update,也叫局部更新)的核心原理,介绍6.3.1版本的Elasticsearch脚本使用实例和增量更新的优势. 增量更新过程与原理 简单回顾 前文我们有简单介绍过增量的语法,简单回顾一下请求示例: POST /music/children/1/_update { "doc": { "length": "76" } } 一般从客户端到Elasticsearch,完整的应用请求流程基本是这样的: 客户

深入理解javascript作用域系列第一篇——内部原理

× 目录 [1]编译 [2]执行 [3]查询[4]嵌套[5]异常[6]原理 前面的话 javascript拥有一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量,这套规则被称为作用域.作用域貌似简单,实则复杂,由于作用域与this机制非常容易混淆,使得理解作用域的原理更为重要.本文是深入理解javascript作用域系列的第一篇——内部原理 内部原理分成编译.执行.查询.嵌套和异常五个部分进行介绍,最后以一个实例过程对原理进行完整说明 编译 以var a = 2;为例,说明javasc

TRUNCATE TABLE恢复系列一:深层剖析内部原理

叮叮铛-今天我们推出Oracle异常恢复的第一个系列:"TRUNCATE TABLE恢复系列",这个系列主要围绕truncate table实现的内部原理和几种恢复方式来展开. 深层剖析内部原理 众所周知,truncate table是一种快速清空表内数据的一种方式,与delete方式不同,truncate只产生非常少的redo和undo,就实现了清空表数据并降低表HWM的功能.我们通过10046和redo dump来分析truncate的整个操作过程,其中10046用于观察trunc

JVM 内部原理系列

JVM 内部原理(一)- 概述 JVM 内部原理(二)- 基本概念之字节码 JVM 内部原理(三)- 基本概念之类文件格式 JVM 内部原理(四)- 基本概念之 JVM 结构 JVM 内部原理(五)- 基本概念之 Java 虚拟机官方规范文档,第 7 版 JVM 内部原理(六)- Java 字节码基础之一 JVM 内部原理(七)- Java 字节码基础之二 原文地址:https://www.cnblogs.com/kaleidoscope/p/9792619.html

Es官方文档整理-2.分片内部原理

Es官方文档整理-2.分片内部原理 1.集群 一个运行的Elasticsearch实例被称为一个节点,而集群是有一个或多个拥有相同claster.name配置的节点组成,他们共同承担数据和负载压力,当有节点加入或从集群中移除的时候,集群或自动平局分布所有数据. 当一个节点被选举成为主节点时,他哈不负责额管理集群范围内的所有变更,例如增加.删除索引,或者增加.删除节点等.而主节点不涉及文档级别的变更和搜索操作,所以集群只有一个主节点,即使流量增加,他也不会成为瓶颈.任何节点都可以成为主节点. 3.

Elasticsearch系列---补充几个知识点

概要 bulk api有趣的json格式 前面<简单入门实战>一节中,有介绍bulk的使用示例,大家一定很奇怪,还有这么有趣的JSON格式,必须严格照他的换行来做,我想把JSON搞得美观可读性好一点,居然给我报错! {"action": {"meta"}}\n {"data"}\n {"action": {"meta"}}\n {"data"}\n 它为什么要这样规定? 我们

Elasticsearch系列---全面了解Document

概要 本篇主要介绍一下document的知识,对document的元数据和基本的语法进行讲解. document核心元数据 前面入门实战一节有简单介绍过document数据示例,这次我们来详细了解一下它的核心元数据,查询响应报文如下: { "_index": "music", "_type": "children", "_id": "1", "_version": 1

【转载】深入研究Windows内部原理绝对经典的资料

原文:深入研究Windows内部原理绝对经典的资料 另一篇资料:深入研究Windows内部原理系列 (为了方便大家下,我打包了放在一下地址: 1-6:http://download.csdn.net/detail/wangqiulin123456/4601530 7-12:http://download.csdn.net/detail/wangqiulin123456/4601508 13-16:http://download.csdn.net/detail/wangqiulin123456/4

JavaScript内部原理实践——真的懂JavaScript吗?(转)

通过翻译了Dmitry A.Soshnikov的关于ECMAScript-262-3 JavaScript内部原理的文章, 从理论角度对JavaScript中部分特性的内部工作机制有了一定的了解.但是,邓爷爷说过:“实践才是检验真理的唯一标准”.所以,我打算通过从内部原理来解释一些经常在笔试或者面试中遇到的关于JavaScript语言层面的题目来进一步学习和掌握JavaScript内部工作原理. 那么,首先就是要去找那些题目,google了一圈终于找到了来自Dmitry Baranovskiy的