5 Elasticsearch 篇之分布式特性介绍

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bingdianone/article/details/86606018

分布式介绍及cerebro

分布式特性:

es支持集群模式,是一个分布式系统,其好处主要有两个:

  • 增大系统容量,如内存、磁盘,使得es集群可以支持PB级的数据。-提高系统可用性,即使部分节点停止服务,整个集群依然可以正常服务

es集群由多个es实例组成

  • 不同集群通过集群名字来区分,可通过cluster.name进行修改,默认为elasticsearch
  • 每个es实例本质上是一个JVM进程,且有自己的名字,通过node.name进行修改

cerebro安装地址:
http://github.com/lmenezes/cerebro
解压运行/bin/cerebro
在这里插入图片描述
es集群相关的数据称为cluster state ,主要记录如下信息:

  • 节点信息,比如节点名称、连接地址等
  • 索引信息,比如索引名称、配置等
  • ……
    在这里插入图片描述

Master Node

  • 可以修改cluster state的节点称为master节点,一个集群只能有一个-cluster state存储在每个节点上, master维护最新版本并同步给其他节点
  • master节点是通过集群中所有节点选举产生的,可以被选举的节点称为master-eligible节点,相关配置如下:
    • node.master:true
      在这里插入图片描述

创建一个索引

我们通过如下api创建一个索引

PUT test_index
在这里插入图片描述

Coordinating Node

.处理请求的节点即为coordinating节点,该节点为所有节点的默认角色,不能取消

·路由请求到正确的节点处理,比如创建索引的请求到master节点
在这里插入图片描述
Data Node
存储数据的节点即为data节点,默认节点都是data类型,相关配置如下:

  • node.data: true
    在这里插入图片描述

副本与分片

提高系统的可用性

服务可用性

  • 2个节点的情况下,允许其中1个节点停止服务

数据可用性

  • 引入副本(Replication)解决
  • 每个节点上都有完备的数据

副本

如下图所示, node2上是test index的副本
在这里插入图片描述

增大系统容量

如何将数据分布于所有节点上?

  • 引入分片( Shard )解决问题

分片是es支持PB级数据的基石

  • 分片存储了部分数据,可以分布于任意节点上
  • 分片数在索引创建时指定且后续不允许再更改,默认为5个
  • 分片有主分片和副本分片之分,以实现数据的高可用
  • 副本分片的数据由主分片同步,可以有多个,从而提高读取的吞吐量

分片

下图演示的是3个节点的集群中test index的分片分布情况,创建时我们指定了3个分、和1个副本, api如下所示:
在这里插入图片描述
在这里插入图片描述
此时增加节点是否能提高test_index的数据容量?
此时增加副本数是否能提高test_index的读取吞吐量?
在这里插入图片描述
此时增加节点是否能提高testindex的数据容量?

  • 不能。因为只有3个分片,已经分布在3台节点上,新增的节点无法利用。
    在这里插入图片描述
    .此时增加副本数是否能提高testindex的读取吞吐量?
  • 不能。因为新增的副本也是分布在这3个节点上,还是利用了同样的资源。如果要增加吞吐量,还需要新增节点。
    在这里插入图片描述
    分片数的设定很重要,需要提前规划好
  • 过小会导致后续无法通过增加节点实现水平扩容
  • 过大会导致一个节点上分布过多分片,造成资源浪费,同时会影响查询性能

集群状态

Cluster Health

通过如下api可以查看集群健康状况,包括以下三种

  • green健康状态,指所有主副分片都正常分配.
  • yellow指所有主分片都正常分配,但是有副本分片未正常分配
  • red有主分片未分配
    在这里插入图片描述
    在这里插入图片描述

故障转移

node1所在机器宕机导致服务终止,此时集群会如何处理?

  1. node2和node3发现nodel无法响应一段时间后会发起master选举,比如这里选择node2为master节点。此时由于主分片P0下线,集群状态变为Red,
    在这里插入图片描述
  2. node2发现主分片P0未分配,将R0提升为主分片。此时由于所有主分片都正常分配,集群状态变为Yellow.
    在这里插入图片描述
  3. node2为P0和P1生成新的副本,集群状态变为绿色
    在这里插入图片描述

文档分布式存储

文档最终会存储在分片上,如下图所示:

  • Document 1最终存储在分片P1上
    在这里插入图片描述
    Document 1是如何存储到分片P1的?选择P1的依据是什么?
  • 需要文档到分片的映射算法

.目的

  • 使得文档均匀分布在所有分片上,以充分利用资源

·算法

  • 随机选择或者round-robin算法?
  • 不可取,因为需要维护文档到分片的映射关系,成本巨大
  • 根据文档值实时计算对应的分片

文档到分片的映射算法
es通过如下的公式计算文档对应的分片

  • shard = hash(routing) % number_of_primary_shards
  • hash算法保证可以将数据均匀地分散在分片中
  • routing是一个关键参数,默认是文档id ,也可以自行指定
  • number_of_primary_shards是主分片数

该算法与主分片数相关,这也是分片数一旦确定后便不能更改的原因

文档创建的流程

  1. Client向node3发起创建文档的请求
  2. node3通过routing计算该文档应该存储在Shard 1上,查询cluster state后确认主分片P1在 node2上,然后转发创建文档的请求到node2 .
  3. P1接收并执行创建文档请求后,将同样的请求发送到副本分片R1
  4. R1接收并执行创建文档请求后,通知P1成功的结果,
  5. P1接收副本分片结果后,通知node3创建成功,
  6. node3返回结果到Client
    在这里插入图片描述

文档读取的流程

  1. Client向node3发起获取文档1的请求
  2. node3通过routing计算该文档在Shard 1上,查询cluster state后获取Shard 1的主副分片列表,然后以轮询的机制获取一个shard,比如这里是R1 ,然后转发读取文档的请求到node1
  3. R1接收并执行读取文档请求后,将结果返回node3
  4. node3返回结果给Client
    在这里插入图片描述

文档批量创建的流程

  1. Client向node3发起批量创建文档的请求(bulk)
  2. node3通过routing计算所有文档对应的shard ,然后按照主shard分配对应执行的操作,同时发送请求到涉及的主shard,比如这里3个主shard都需要参与
  3. 主shard接收并执行请求后,将同样的请求同步到对应的副本shard
  4. 副本shard执行结果后返回结果到主shard,主shard再返回node3
  5. node3整合结果后返回Client后5、node3整合结果后返回Client后
    在这里插入图片描述

文档批量读取的流程

  1. Client向node3发起批量获取文档的请求(mget)
  2. node3通过routing计算所有文档对应的shard ,然后以轮询的机制获取要参与shard ,按照shard " 构建mget请求,同时发送请求到涉及的shard ,比如这里有2个shard需要参与
  3. R1, R2返回文档结果
  4. node3返回结果给Client
    在这里插入图片描述

脑裂问题

·脑裂问题,英文为split-brain ,是分布式系统中的经典网络问题,如下图所示:

  • 3个节点组成的集群,突然nodel的网络和其他两个节点中断
  • node2与node3会重新选举master ,比如node2成为了新master ,此时会更新 cluster state
  • node1自己组成集群后,也会更新cluster state·同一个集群有两个master ,而且维护不同的cluster state ,网络恢复后无法选择正确的主
    在这里插入图片描述
    在这里插入图片描述
    解决方案为仅在可选举master-eligible节点数大于等于quorum时才可以进行master选举
  • quorum = master-eligible节点数/2 +1,例如3个master-eligible节点时, quorum为2.
  • 设定discovery.zen.minimum_master_nodes为quorum即可避免脑裂
    在这里插入图片描述

shard详解

倒排索引的不可变更

倒排索引一旦生成,不能更改
其好处如下:

  • 不用考虑并发写文件的问题,杜绝了锁机制带来的性能问题
  • 由于文件不再更改,可以充分利用文件系统缓存,只需载入一次,只
    要内存足够,对该文件的读取都会从内存读取,性能高
  • 利于生成缓存数据
  • 利于对文件进行压缩存储,节省磁盘和内存存储空间

坏处为需要写入新文档时,必须重新构建倒排索引文件,然后替换老文件后,新文档才能被检索,导致文档实时性差,
在这里插入图片描述

文档搜索实时性

解决方案是新文档直接生成新的倒排索引文件,查询的时候同时查询所有的倒排文件,然后做结果的汇总计算即可
在这里插入图片描述
Lucene便是采用了这种方案,它构建的单个倒排索引称为segment ,合在一起称为 Index,与ES中的Index概念不同。ES中的一个Shard对应一个Lucene Index.

Lucene会有一个专门的文件来记录所有的segment信息,称为commit point
在这里插入图片描述

文档搜索实时性-refresh

refresh发生的时机主要有如下几种情况:

  • 间隔时间达到时,通过index.settings.refresh_interval来设定,默认是1秒 .
  • index.buffer占满时,其大小通过indices.memory.index_buffer_size设置,默认为jvm heap的10%,所有shard共享
  • flush发生时也会发生refresh

segment写入磁盘的过程依然很耗时,可以借助文件系统缓存的特性,先将segment在缓存中创建并开放查询来进一步提升实时性,该过程在es中被称为refresh.

在refresh之前文档会先存储在一个buffer中, refresh时将buffer中的所有文档清空并生成segment

es默认每1秒执行一次refresh ,因此文档的实时性被提高到1秒,这也是es被称为近实时(Near Real Time)的原因
在这里插入图片描述
在这里插入图片描述

文档搜索实时性-translog

·如果在内存中的segment还没有写入磁盘前发生了宕机,那么其中的文档就无法恢复了,如何解决这个问题?

  • es引入translog机制。写入文档到buffer时,同时将该操作写入translog
  • translog文件会即时写入磁盘(fsync) , 6.x默认每个请求都会落盘,可以修改为每5秒写一次,这样风险便是丢失5秒内的数据,相关配置为index.translog.*
  • es启动时会检查translog文件,并从中恢复数据
    在这里插入图片描述
    在这里插入图片描述

文档搜索实时性-flush

flush负责将内存中的segment写入磁盘,主要做如下的工作:

  • 将translog写入磁盘
  • 将index buffer清空,其中的文档生成一个新的segment ,相当于一个refresh操作
  • 更新commit point并写入磁盘·执行fsync操作,将内存中的segment写入磁盘·删除旧的translog文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    flush发生的时机主要有如下几种情况:
  • 间隔时间达到时,默认是30分钟, 5.x之前可以通过 index.translog.flush_threshold_period修改,之后无法修改 .
  • translog占满时,其大小可以通过index.translog.flush_threshold_ size控制,默认是512mb ,每个index有自己的translog

文档搜索实时性-删除与更新文档

. segment一旦生成就不能更改,那么如果你要删除文档该如何操作?

  • Lucene专门维护一个.del的文件,记录所有已经删除的文档,注意.del上记录的是文档在Lucene内部的id
  • 在查询结果返回前会过滤掉.del中的所有文档

·更新文档如何进行呢?

  • 首先删除文档,然后再创建新文档

整体视角

ES Index与Lucene Index的术语对照如下所示:
在这里插入图片描述

Sagment Merging

·随着segment的增多,由于一次查询的segment数增多,查询速度会变慢

.es会定时在后台进行segment merge的操作,减少segment的数量

·通过force-merge api可以手动强制做segment merge的操作

猜你喜欢

转载自blog.csdn.net/bingdianone/article/details/86606018
今日推荐