副本数量的选定原则
对于副本数,比较好确定,可以根据我们集群节点的多少与我们的存储空间决定,我们的集群服务器多,并且有足够大多存储空间,可以多设置副本数,一般是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