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

1.集群
     一个运行的Elasticsearch实例被称为一个节点,而集群是有一个或多个拥有相同claster.name配置的节点组成,他们共同承担数据和负载压力,当有节点加入或从集群中移除的时候,集群或自动平局分布所有数据。
     当一个节点被选举成为主节点时,他哈不负责额管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。而主节点不涉及文档级别的变更和搜索操作,所以集群只有一个主节点,即使流量增加,他也不会成为瓶颈。任何节点都可以成为主节点。
 
 
3.添加索引
     PUT /blogs
     {
          "settings":{
               "number_of_shards":3,
               "number_of_replicas":1
          }
     }
设置三个主分片,1个复制分片。
 
4.水平扩展
     PUT /blogs/_settings
     {
         "number_of_replicas":2 
     }
复制分片从一个增加到两个。不能修改主分片个数。
 
5.路由一个文档到分片
     当索引一个文档时,文档会被存储到主分片中。存到哪个主分片由下面这个公式决定:
shard = hash(routing) % number_of_primary_shards.
     routing是一个可变值,默认是文档_id,也可以设置一个自定义的值。
     number_of_primary_shards主分片数。
     这里解释了为什么不能改变主分片数量:因为如果数量变化了,那么所有的之前路由的值都会无效,文档也找不到了。
 
6.新建、索引和删除单个文档
     1).客户端向集群中的一个节点(协调节点)发送请求。
     2).节点使用文档的_id确定文档所属的分片,转发请求到分片所属的节点(master).
     3).主分片执行请求。若执行成功,将请求并行转发到复制节点。一旦所有复制节点报告执行成功。master节点向协调节点报告成功,协调节点向客户端报告成功。
 
7.检索单个文档
     1).客户端向集群中的一个节点(node1)发出请求。
     2).node1节点使用_id确定文档所属分片,将请求转发大其中个一个分片所属节点(node2)。
     3).node2将文档返回给node1,然后将文档返回给客户端。
协调节点每次请求的时候选择不同的副本分片达到负载均衡。
 
8.局部更新
     1).客户端向node1发送更新请求。
     2).转发请求到主分片所在的node2。
     3).node2从主分片检索文档,修改_source字段中的JSON,并尝试重新索引主分片文档。如果文档已经被另一个进程修改了,他将重试步骤3,超过retry_on_conflict次后放弃。
     4).如果node2成功更新索引,它将新版本的文档转发到所有副本分片所在的节点,重新建立索引。一旦所有副本分片都成功返回了,node2向协调节点返回成功,协调节点向客户端返回成功。
 
9.倒排索引
     Elasticsearch使用一种称为倒排索引的结构,它适用于快速的全文搜索。一个倒排索引有文档中所有不重复的词的列表构成,对于其中每个词,有一个包含他的文档列表。类似下面:(被索引的字段都有自己的倒排索引)
Term  | Doc 1 | Doc 2 | Doc 3 | ...
------------------------------------
brown |   X   |        |  X    | ...
fox      |   X   |   X   |  X    | ...
quick   |   X   |   X   |        | ...
the      |   X   |        |  X    | ...
它会保存每一个词项出现过的文档总数, 在对应的文档中一个具体词项出现的总次数,词项在文档中的顺序,每个文档的长度,所有文档的平均长度,等等。
不变性:
倒排索引被芯茹磁盘后是不可改变的:它永远不会被修改。不可修改的意义:
     1).不需要锁。
     2).写入单个大的倒排索引允许被压缩。
     3).一旦索引被读入内核的文件系统缓存,便会留在哪里,由于其不变性。只要文件系统缓存中还有足够的空间,那么大部分读请求会直接请求内存,而不会命中磁盘。这提供了很大的性能提升。
     4).其它缓存(像filter缓存),在索引的生命周期内始终有效。它们不需要在每次数据改变时被重建,因为数据不会变化。
 
     当然,一个不变的索引也有不好的地方。主要事实是它是不可变的! 你不能修改它。如果你需要让一个新的文档 可被搜索,你需要重建整个索引。这要么对一个索引所能包含的数据量造成了很大的限制,要么对索引可被更新的频率造成了很大的限制。
 
10.动态更新索引
     Elasticsearch 基于 Lucene, 这个 java 库引入了 按段搜索(per-segment search) 的概念。 每一 segment 本身都是一个倒排索引, 但 索引 在 Lucene 中除表示所有 segment 的集合外, 还增加了 提交点 的概念 — 一个列出了所有已知段的文件。
 
     索引与分片的比较:
     被混淆的概念是,一个 Lucene 索引 我们在 Elasticsearch 称作 分片 。 一个 Elasticsearch 索引 是分片的集合。 当 Elasticsearch 在索引中搜索的时候, 他发送查询到每一个属于索引的分片(Lucene 索引),然后像 执行分布式检索 提到的那样,合并每个分片的结果到一个全局的结果集。
 
一个 Lucene 索引包含一个提交点和三个段:
 
一个在内存缓存中包含新文档的 Lucene 索引:
在一次提交后,一个新的segment被添加到提交点而且缓存被清空:
     1).新文档被收集到内存索引缓存, “一个在内存缓存中包含新文档的 Lucene 索引” 。
     2).不时地, 缓存被 提交 :
          一个新的segment --一个追加的倒排索引--被写入磁盘。
          一个新的包含新segment 名字的 提交点 被写入磁盘。
          磁盘进行 同步 — 所有在文件系统缓存中等待的写入都刷新到磁盘,以确保它们被写入物理文件。
     3).新的segment 被开启,让它包含的文档可见以被搜索。
     4).内存缓存被清空,等待接收新的文档。
删除和更新:
     段是不可改变的,所以既不能从把文档从旧的段中移除,也不能修改旧的段来进行反映文档的更新。 取而代之的是,每个提交点会包含一个 .del 文件,文件中会列出这些被删除文档的段信息。
     当一个文档被 “删除” 时,它实际上只是在 .del 文件中被 标记 删除。一个被标记删除的文档仍然可以被查询匹配到, 但它会在最终结果被返回前从结果集中移除。
文档更新也是类似的操作方式:当一个文档被更新时,旧版本文档被标记删除,文档的新版本被索引到一个新的段中。 可能两个版本的文档都会被一个查询匹配到,但被删除的那个旧版本文档在结果集返回前就已经被移除。
 
11.近实时搜索
     随着按段(per-segment)搜索的发展, 一个新的文档从索引到可被搜索的延迟显著降低了。新文档在几分钟之内即可被检索,但这样还是不够快。
     磁盘在这里成为了瓶颈。提交(Commiting)一个新的段到磁盘需要一个 fsync 来确保段被物理性地写入磁盘,这样在断电的时候就不会丢失数据。 但是 fsync 操作代价很大; 如果每次索引一个文档都去执行一次的话会造成很大的性能问题。
     我们需要的是一个更轻量的方式来使一个文档可被搜索,这意味着 fsync 要从整个过程中被移除。
     在Elasticsearch和磁盘之间是文件系统缓存,在内存索引缓冲区中的文档会被写入到一个新的segment中。 但是这里新段会被先写入到文件系统缓存--这一步代价会比较低,稍后再被刷新到磁盘--这一步代价比较高。不过只要文件已经在缓存中, 就可以像其它文件一样被打开和读取了。 
在内存缓冲区中包含了新文档的 Lucene 索引: 
缓冲区的内容已经被写入一个可被搜索的段中,但还没有进行提交:
Refresh API
     在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做 refresh 。 默认情况下每个分片会每秒自动刷新一次。这就是为什么我们说 Elasticsearch 是 近 实时搜索: 文档的变化并不是立即对搜索可见,但会在一秒之内变为可见。
     POST /_refresh :刷新(Refresh)所有的索引。
     POST /blogs/_refresh :只刷新(Refresh) blogs 索引。
     并不是所有的情况都需要每秒刷新。可能你正在使用 Elasticsearch 索引大量的日志文件, 你可能想优化索引速度而不是近实时搜索, 可以通过设置 refresh_interval , 降低每个索引的刷新频率:
     PUT /my_logs
     {
            "settings": {
            "refresh_interval": "30s"
       }
     }
     在生产环境中,当你正在建立一个大的新索引时,可以先关闭自动刷新,待开始使用该索引时,再把它们调回来:
PUT /my_logs/_settings
{ "refresh_interval": -1 }
 
PUT /my_logs/_settings
{ "refresh_interval": "1s" }
 
12.持久化变更
     如果没有用 fsync 把数据从文件系统缓存刷(flush)到硬盘,我们不能保证数据在断电甚至是程序正常退出之后依然存在。为了保证 Elasticsearch 的可靠性,需要确保数据变化被持久化到磁盘。
      Elasticsearch 增加了一个 translog ,或者叫事务日志,在每一次对 Elasticsearch 进行操作时均进行了日志记录。通过 translog ,整个流程看起来是下面这样:
          1).一个文档被索引之后,就会被添加到内存缓冲区,并且 追加到了 translog.
          2).刷新(refresh)使分片,分片每秒被刷新(refresh)一次:
               a.这些在内存缓冲区的文档被写入到一个新的段中,且没有进行 fsync 操作。   ** 这个段被打开,使其可被搜索。
               b.内存缓冲区被清空。
          3).这个进程继续工作,更多的文档被添加到内存缓冲区和追加到事务日志.
          4).每隔一段时间--例如 translog 变得越来越大--索引被刷新(flush);一个新的 translog 被创建,并且一个全量提交被执行:
               a.所有在内存缓冲区的文档都被写入一个新的段。
               b.缓冲区被清空。
               c.一个提交点被写入硬盘。
               d.文件系统缓存通过 fsync 被刷新(flush)。
               e.老的 translog 被删除。 
     translog 提供所有还没有被刷到磁盘的操作的一个持久化纪录。当 Elasticsearch 启动的时候, 它会从磁盘中使用最后一个提交点去恢复已知的段,并且会重放 translog 中所有在最后一次提交后发生的变更操作。
     Flush API
          这个执行一个提交并且截断 translog 的行为在 Elasticsearch 被称作一次 flush 。 分片每30分钟被自动刷新(flush),或者在 translog 太大的时候也会刷新。可以手动刷新:
               POST /blogs/_flush
               POST /_flush?wait_for_ongoing
Translog 的安全问题:默认,在每次请求后都会通过fsync把请求写到日志文件。你也可以使用异步的 fsync ,写入的数据被缓存到内存中,每5秒执行一次 fsync :
PUT /my_index/_settings
{
    "index.translog.durability": "async",
    "index.translog.sync_interval": "5s"
}
 
13.segment合并
     由于自动刷新流程每秒会创建一个新的segment ,这样会导致短时间内的segment 数量暴增。而segment 数目太多会带来较大的麻烦。 每一个segment 都会消耗文件句柄、内存和cpu运行周期。更重要的是,每个搜索请求都必须轮流检查每个segment ;所以segment 越多,搜索也就越慢。
     Elasticsearch通过在后台进行segment 合并来解决这个问题。小的segment 被合并到大的segment ,然后这些大的segment 再被合并到更大的segment 。
     segment 合并的时候会将那些旧的已删除文档 从文件系统中清除。 被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大segment 中。
启动segment 合并不需要你做任何事。进行索引和搜索时会自动进行。
     1).当索引的时候,刷新(refresh)操作会创建新的segment 并将segment 打开以供搜索使用。
     2).合并进程选择一小部分大小相似的segment ,并且在后台将它们合并到更大的segment 中。这并不会中断索引和搜索。
     3).一旦合并结束,老的段被删除, 说明合并是完成的活动:
          a.新的段被刷新(flush)到了磁盘。   ** 写入一个包含新段且排除旧的和较小的段的新提交点。
          b.新的段被打开用来搜索。
          c.老的段被删除。
     合并大的segment需要消耗大量的I/O和CPU资源,如果任其发展会影响搜索性能。Elasticsearch在默认情况下会对合并流程进行资源限制,所以搜索仍然 有足够的资源很好地执行。
 
Optimize API
     optimize API大可看做是 强制合并 API 。它会将一个分片强制合并到 max_num_segments 参数指定大小的段数目。 这样做的意图是减少段的数量(通常减少到一个),来提升搜索性能。
     optimize API 不应该 被用在一个动态索引————一个正在被活跃更新的索引。后台合并流程已经可以很好地完成工作。 optimizing 会阻碍这个进程。不要干扰它!
     在特定情况下,使用 optimize API 颇有益处。例如在日志这种用例下,每天、每周、每月的日志被存储在一个索引中。 老的索引实质上是只读的;它们也并不太可能会发生变化。在这种情况下,使用optimize优化老的索引,将每一个分片合并为一个单独的段就很有用了;这样既可以节省资源,也可以使搜索更加快速:
     POST /logstash-2014-10/_optimize?max_num_segments=1
     请注意,使用 optimize API 触发段合并的操作一点也不会受到任何资源上的限制。这可能会消耗掉你节点上全部的I/O资源, 使其没有余裕来处理搜索请求,从而有可能使集群失去响应。 如果你想要对索引执行 `optimize`,你需要先使用分片分配(查看 迁移旧索引)把索引移到一个安全的节点,再执行。 

Es官方文档整理-2.分片内部原理的更多相关文章

  1. Es官方文档整理-3.Doc Values和FieldData

    Es官方文档整理-3.Doc Values和FieldData 1.Doc Values 聚合使用一个叫Doc Values的数据结构.Doc Values使聚合更快.更高效且内存友好. Doc Va ...

  2. 国家密码标准-商密SM2官方文档整理

    SM2官方文档整理 算法原理 SM2算法介绍 我国自主知识产权的商业密码算法,是ECC(椭圆加密算法)的一种,基于椭圆曲线离散对数问题(公钥密码体制所依据的难题主要为大素数分解问题.离散对数问题.椭圆 ...

  3. 【苦读官方文档】2.Android应用程序基本原理概述

    官方文档原文地址 应用程序原理 Android应用程序是通过Java编程语言来写.Android软件开发工具把你的代码和其它数据.资源文件一起编译.打包成一个APK文件,这个文档以.apk为后缀,保存 ...

  4. OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)和varying,uniform,attribute修饰范围

    OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)   所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符. ...

  5. 微信小程序官方文档错误整理

    大致看了一遍微信小程序文档,发现有几处微小的错误,但瑕不掩瑜.记录下,以后发现了还会继续在此添加.如果有记录不对的,请及时指出错误. 1.视图层->WXSS->尺寸单位 明显错误,应该为 ...

  6. OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)

    OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...

  7. OpenGL ES着色器语言之操作数(官方文档第五章)

    OpenGL ES着色器语言之操作数(官方文档第五章) 5.1操作数 OpenGL ES着色器语言包含如下操作符. 5.2数组下标 数组元素通过数组下标操作符([ ])进行访问.这是操作数组的唯一操作 ...

  8. OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)

    OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...

  9. OpenGL ES着色器语言之着色概览(官方文档)

    OpenGL ES着色器语言之着色概览(官方文档第二章) 事实上,OpenGL ES着色语言是两种紧密关联的语言.这些语言用来在OpenGL ES处理管线的可编程处理器创建着色器. 在本文档中,除非另 ...

随机推荐

  1. 读论文Machine Learning for Improved Diagnosis and Prognosis in Healthcare

    Deep Learning的基本思想 假设我们有一个系统S,它有n层(S1,…Sn),它的输入是I,输出是O,形象地表示为: I =>S1=>S2=>…..=>Sn => ...

  2. bzoj 2055 80人环游世界

    有源汇上下界最小费用可行流. 将每个国家拆点. 源点向一个新建节点连一条上界为总人数下界为0费用为0的边. 新建节点向每个国家的入点连一条上界为正无穷下界为0费用为0的边. 每个国家的入点向出点连一条 ...

  3. Python高手之路【四】python函数装饰器,迭代器

    def outer(func): def inner(): print('hello') print('hello') print('hello') r = func() print('end') p ...

  4. ShareRepository

    文件共享下载链接: 1:关于模拟器的配置附件http://pan.baidu.com/s/1jGFqfh8 原文地址:http://www.cnblogs.com/killerlegend/p/382 ...

  5. Java消息队列三道面试题详解!

    面试题 为什么使用消息队列? 消息队列有什么优点和缺点? Kafka.ActiveMQ.RabbitMQ.RocketMQ 都有什么区别,以及适合哪些场景? 面试官心理分析 其实面试官主要是想看看: ...

  6. Linux下编译Phantomjs

    1.安装依赖的库 <pre> sudo apt-get install g++ flex bison gperf ruby perl \ libsqlite3-dev libfontcon ...

  7. [转载]如何做到 jQuery-free?

    http://www.ruanyifeng.com/blog/2013/05/jquery-free.html jQuery是现在最流行的JavaScript工具库. 据统计,目前全世界57.3%的网 ...

  8. debian旧日笔记

    18:45 2007-10-7 序 图形界面较好的Linux操作系统有三个主要的发行版本:RedHat, Debian, SuSE.自RedHat9后,RedHat以Fedora为名发行新的版本.仍然 ...

  9. IDEA 2017 破解

    一.windows 1.进入hosts文件中:C:\Windows\System32\drivers\etc\hosts 2.将"0.0.0.0 account.jetbrains.com& ...

  10. element-UI 表单图片判空验证问题

    本文地址:http://www.cnblogs.com/veinyin/p/8567167.html  element-UI的表单验证似乎并没有覆盖到文件上传上面,当我们需要在表单里验证图片时,就会出 ...