Elasticsearch分片数量选择及如何保证数据一致性

副本数量的选定原则

对于副本数,比较好确定,可以根据我们集群节点的多少与我们的存储空间决定,我们的集群服务器多,并且有足够大多存储空间,可以多设置副本数,一般是1-3个副本数,如果集群服务器相对较少并且存储空间没有那么宽松,则可以只设定一份副本以保证容灾(副本数可以动态调整)

举个栗子:

#在一个三节点组成的集群中 设置一个主分片数为5,副分片为0的索引
PUT /haizhi1
{
    "settings": {
        "index": {
            "number_of_shards": 5,
            "number_of_replicas": 0
        }
    }
}

副分片数量为0则意味着集群中的任何一台机器宕机,都会导致集群不可用,数据不完整。

副本数量是可以动态修改的

PUT /haizhi1/_settings
{
    "settings": {
        "index": {
            "number_of_replicas": 1
        }
    }
}

动态修改数据副本为1,可以容忍一台机器宕机,提高可用性

模块简介

Elasticsearch集群中保持数据一致性的过程中,涉及到内部之间的通讯,先简单介绍一下es中各模块的作用和功能

1)cluster

cluster模块是主节点执行集群管理和封装的实现,管理集群状态,维护集群层面的配置信息。

  • 管理集群状态,将新生成的集群状态发布到集群中所有的节点
  • 调用allocation模块执行分片分配,决策哪些分片应该分配到哪个节点
  • 在集群各节点中直接迁移分片,保持数据平衡

2)allocation

封装了分片分配相关的功能和策略,包括主分片的分配和副分片的分配,本模块由主节点调用。创建新索引、集群完全重启都需要分片分配的过程

3)discovery

发现模块负责发现集群中的节点,以及选举主节点,当节点加入或者退出集群是,主节点会采取像一个的行动(选主或者是集群拓扑)。

4)gateway

负责对收到 Master 广播下来的集群状态( cluster state )数据的持久化存储,并在集群完全重启时恢复它们 。

5)Indices

索引模块管理全局级的索引设置,不包括索引级的(索引设置分为全局级和每个索引级)。 它还封装了索引数据恢复功能 。 集群启动阶段需要的主分片恢复和副分片恢复就是在这个模块 实现的 。

6)HTTP

HTTP 模块允许通过 JSON over HTTP 的方式访 问 ES 的 API, HTTP 模块本质上是完全异步的,这意味着没有阻塞线程等待响应 。

7)Transport

传输模块用于集群内节点之间的内部通信 。 从一个节点到另 -个节点的每个请求都使用传输模块。 如同 HTTP 模块 ,传输模块本质上也是完全异步的。传输模块使用 TCP 通信,每个节点都与其他节点维持若干 TCP 长连接。内 部节点间的所有通信都是本模块承载的。

8)Engine

Engine 模块封装了对 Lucene 的操作及 translog 的调用,它是对一个分片读写操作的最终提供者 。

写操作如何保证数据的一致性

算法概念

ES的数据副本模型基于主从模式,是基于微软的PacificA算法实现,PecificA的算法特点如下:

  • Replica Group: 一个互为副本的的数据集合称为副本组,该副本组中只有一个副本是主数据(Primary),

    其他的都为从数据(Secondary),在ES则是我们对应的主分片和副分片。

  • Configuration: 配置信息中描述了一个副本组中的副本信息(谁是主数据,谁是从数据,分别位于哪个节点)

  • Configuration Version:配置信息的版本号,每次发生变更时递增

  • Serial Number:代表每个写操作的数据,每次写操作是会将该值递增,简称SN。每个主副本维护自己的递增SN

  • Prepared List:写操作的准备序列。存储来自外部的请求列表,将请求按照SN进行从小到大排序

  • Committed List:写操作的顺序提交

新建、索引和删除请求都是写操作,写操作必须先在主分片执行成功后,才能复制到相应的副本组中的其他副分分片

[外链图片转存失败(img-7e7Iqlmw-1567323878796)(/Users/haizhi/Library/Application Support/typora-user-images/image-20190707100909138.png)]

1)写请求进入到协调节点,协调节点通过ID进行转发

2)写操作进入主副本节点(Primary),主副本节点为该操作分配SN,使用该SN构建写操作请求数据结构(UpdateRequest),然后将该UpdateRequest写入自己的prepare list。

3)一旦主副本节点收到所有从副本节点收到所有的从副本节点的相应,确定该数据已经被正确写入所有的从副本节点,此时认为可以提交了,将此UpdateRequest放入committed list,

4)主副本回复客户端更新成功。此时,主副本节点向从副本节点发送一个commit通知,告诉所有的副本节点自己的 committed point位置,从副本节点收到通知后根据指示移动到 committed point相同的位置

写一致性默认的策略是qourum,即多数的分片(其中分片副本可以是主分片或副分片)在写入操作的时候处于可用状态

quorum=int( (primary + number_of_replicas) / 2 ) + 1

也可以通过wait_for_active_shards参数来指定必须多少个shard响应写请求才算成功

#设置等待写入结果
PUT /haizhi1/type1/4?wait_for_active_shards=5
{
  "key1":"value12"
}
协调节点的作用和流程

协调节点在整个流程中,负责参数检验,创建索引和转发请求到主分片节点、等待响应并回复客户端

参数检验
参数检查
index不可为空
type不可为空
source不可为空
contentType不可为空
opType当前操作类型如果是创建索引,则校验VersionType必须为internal,且Version不可为MATCH_DELETED
resolvedVersion校验解析的Version是否合法
versionType不可为FORCE类型,此类型已废弃
id非空是,长度不可大于512,以及为空时,则需要对versionType和resolvedVersion的检查
  • 任何一项检查未通过,都会拒绝请求
自动创建索引

如果配置为允许自动创建索引(默认允许),则计算请求中涉及的索引,可能有多个,其中有哪些索引是不存在的,则需要进行创建,如果部分索引创建失败,则实际的请求被标记为失败,其他索引正常执行写流程

创建索引的请求会被转发到Master节点,待收到全部创建请求的结果(无论是成功还是失败),都会进行到处理下一个流程

对请求的预先处理

对请求的预先处理不同于对数据的预处理,只是检查参数,自动生成ID,处理routing

检查集群状态

价差当前集群中是否存在主节点,如果不存在,会阻塞等待主节点的选举直到超时

内容路由,构建基于shard的请求

将用户的bulkRequest重新组织为基于shard的请求列表。

栗子:如果用户请求有10个写操作,会将这10个写操作按照路由算法确定分片是否是同一个,批量操作。

路由算法 : shard_num = hash(_routing) % num_primary_shards

默认情况下 _routing是指文档的ID

ES使用随机id和hash算法来确保文档均匀分布给分片,当使用自定义id或者routing是,id或routing值不够随机,造成数据倾斜,部分分片过大。可以使用index.routing_partition_size配置来减少倾斜的风险,routing_partition_size越大,则数据分布的越均匀。

shard_num = (hash(_routing) + hash(_id) % routing_partition_size) % num_primary_shards

也就是说,一routing 字段用于计算索引中的一组分片,然后使用一id 来选择该组内的分片。 index.routing_partition_size 取值应具有大于等于 1 且小于 index.number_of_ shards 的值。

转发请求并等待响应

根据集群状态中的内容路由表确定主分片所在的节点,转发请求并等待响应

PUT /haizhi1
{
    "settings": {
        "index": {
            "number_of_shards": 5,
            "routing_partition_size":0, #可以再创建索引的时候指定routing_partition_size
            "number_of_replicas": 1
        }
    }
}

主分片节点作用和流程

主分片所在的节点负责在本地写主分片,写成功后(Prepared List),转发写副本请求,等待响应,回复协调节点

检查请求

收到协调节点发来的请求,需要检测要写的是否是朱分片,索引是否处于关闭状态

是否延迟执行

判断是否需要延迟执行,如果需要延迟则放入队列,否则继续往下执行

判断主分片是否发生迁移

如果发生迁移,则转发请求到迁移的节点

检测写一致性

在写操作开始前。检测本次写操作涉及的shard活跃数量是否足够,不足则不执行写入,默认为1,只要主分片可用就执行写入

写Lucene和事物日志

遍历请求,处理动态更新字段映射,然后逐条对doc索引。

索引的过程是先写Lucene,后写translog。

处理副本信息

主分片操作成功后则将请求转发到副分片上

索引恢复流程

索引恢复是ES数据恢复过程,待恢复的数据是客户端写入成功,但未执行刷盘(flush)的Lucene分段。副分片同步主分片数据

根据分片的性质,索引恢复过程可以分为朱分片恢复流程和副分片恢复流程

  • 主分片从translog中自我恢复,尚未执行flush到磁盘lucene分段的数据可以从translog中重建
  • 副分片需要从主分片中拉取Lucene分段和translog进行恢复。

索引恢复的触发条件包括从快照备份恢复,节点加入和离开,索引的_open操作

阶段简介
INIT恢复尚未启动
INDEX恢复Lucene文件,以及在节点间复制索引数据
VERIFY_INDEX验证索引
TRANSLOG启动engine,重放translog,建立Lucene索引
FINALIZE清理工作
DONE完毕

主分片和副分片恢复都会经历这些阶段 ,但有时候会跳过具体执行过程 ,只 是在流程上体 现出 经历了这个短暂阶段 。 例如, 副分片恢复时会跳过 TRANSLOG 重放过程: 主分片恢复过 程中 的卧IDEX 阶段不会在节点之 间 复制数据。

主分片恢复流程
INIT 阶段

一个分片的恢复是从启动开始,检验当前分片是否为主分片,分片状态等信息校验

INDEX阶段

从Lucene读取最后一次提交的分段信息,

VERIFY_INDEX阶段

验证Lucene中的index是否被损坏 是否检验本项检查取决于配置index.shard.check_on_startup,在分片数据过多的时候,分片检查会消耗更多的时间,影响启动速度

TRANSLOG阶段

根据Lucene最后一次提交的记录和translog对比,将需要重新操作的数据遍历重新索引

FINALIZE阶段

本阶段执行刷新(refresh)操作,将缓冲的数据写入文件,但不刷盘,数据还在操作系统的cache中

DONE阶段

DONE阶段将再次执行refresh,然后更新分片状态为恢复完成

副分片恢复流程

副分片恢复的核心思想是从主分片拉取 Lucene 分段和 translog 进行恢复 。 按数据传递的方

向,主分片节点称为 Source ,副分片节点称为 Target。

索引恢复过程的一个难点在于如何维护主副分片的一致性。 假设副分片恢复期间 一直有写

操作,如何实现一致呢?

我们先看看早期的做法:在 2.0 版本之前,副分片恢复要经历三个阶段 。

阶段1 :将主分片的 Lucene 做快照,发送到 target 。期间不阻塞索引操作,新增数据写到主分片的 translog 。 阶段2 : 将主分片 translog 做快照,发送到 target 重放,期间不阻塞索引操作 。

阶段3 : 为主分片加写锁,将剩余的 translog 发送到 target。 此时数据量很小,写入过程的阻塞很短 。

从2.0版本开始 引入 translog.view 概念的同时, 阶段3被删除 。这个阶段是重放操作( operations ),同时防止新的写入 Engine 。 这是不必要的,因为自恢复开始,标准的 index 操作会发送所有的操作到正在恢复中的分片。 重放恢复 开始时获取的 view 中的所有操作足够保证不丢失任何操作 。

阶段1:在主分片所在节点, 获取 translog 保留锁, 从获取保留锁开始,会保留 translog不受其刷盘清空的影响 。然后调用 Lucene 接口把 shard 做快照,快照含有 shard 中己经刷到磁盘的文件引用,把这些 shard 数据复制到副本节点。在 phase1结束前 ,会向副分片节点发送告知对方启动 Engine ,在 phase2 开始之前,副分片就可以正常处理写 请求了。

阶段2 : 对 translog 做快照,这个快照里包含从 phase !开始,到执行 translog 快照期间 的新增索引 。 将这些 translog 发送到副分片所在节点进行重放。

[外链图片转存失败(img-0DvuW7de-1567323878798)(/Users/haizhi/Library/Application Support/typora-user-images/image-20190707182408714.png)]

  • 查看集群中所有索引恢复的状态和进度

  • #查看集群中所有的索引恢复进度
    GET _cat/recovery?v
    
  • 查看单个索引的恢复状态、进度

  • #查看单个索引恢复详情
    GET /haizhi1/_recovery?pretty
    
  • 查看索引恢复状态统计

    GET /_all/_stats?level=shards&pretty
    

    查看索引恢复信息

https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-recovery.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值