单机的elasticsearch
做数据存储,必然面临两个问题:海量数据存储问题、单点故障问题。
- 海量数据存储问题:将索引库从逻辑上拆分为
N
个分片(shard
),存储到多个节点 - 单点故障问题:将分片数据在不同节点备份(
replica
)
ES集群相关概念:
-
集群(
cluster
):一组拥有共同的cluster name
的 节点。 -
节点(
node
) :集群中的一个Elasticearch
实例 -
分片(
shard
):索引可以被拆分为不同的部分进行存储,称为分片。在集群环境下,一个索引的不同分片可以拆分到不同的节点中解决问题:数据量太大,单点存储量有限的问题。
此处,我们把数据分成3片:
shard0
、shard1
、shard2
-
主分片(
Primary shard
):相对于副本分片的定义。 -
副本分片(
Replica shard
)每个主分片可以有一个或者多个副本,数据和主分片一样。
数据备份可以保证高可用,但是每个分片备份一份,所需要的节点数量就会翻一倍,成本实在是太高了!
为了在高可用和成本间寻求平衡,我们可以这样做:
- 首先对数据分片,存储到不同节点
- 然后对每个分片进行备份,放到对方节点,完成互相备份
这样可以大大减少所需要的服务节点数量,如图,我们以3分片,每个分片备份一份为例:
现在,每个分片都有1个备份,存储在3个节点:
node0
:保存了分片0和1node1
:保存了分片0和2node2
:保存了分片1和2
2.集群脑裂问题
2.1.集群职责划分
elasticsearch
中集群节点有不同的职责划分:
默认情况下,集群中的任何一个节点都同时具备上述四种角色。
但是真实的集群一定要将集群职责分离:
master
节点:对CPU
要求高,但是内存要求第data
节点:对CPU
和内存要求都高coordinating
节点:对网络带宽、CPU
要求高
职责分离可以让我们根据不同节点的需求分配不同的硬件去部署。而且避免业务之间的互相干扰。
一个典型的es
集群职责划分如图:
2.2.脑裂问题
脑裂是因为集群中的节点失联导致的。
例如一个集群中,主节点与其它节点失联:
此时,node2
和node3
认为node1
宕机,就会重新选主:
当node3
当选后,集群继续对外提供服务,node2
和node3
自成集群,node1
自成集群,两个集群数据不同步,出现数据差异。
当网络恢复后,因为集群中有两个master
节点,集群状态的不一致,出现脑裂的情况:
解决脑裂的方案是,要求选票超过( eligible节点数量 + 1 )/ 2
才能当选为主,因此eligible
节点数量最好是奇数。对应配置项是discovery.zen.minimum_master_nodes
,在es7.0
以后,已经成为默认配置,因此一般不会发生脑裂问题
例如:3个节点形成的集群,选票必须超过 (3 + 1) / 2
,也就是2票。node3
得到node2
和node3
的选票,当选为主。node1
只有自己1票,没有当选。集群中依然只有1个主节点,没有出现脑裂。
2.3.小结
master eligible
节点的作用是什么?
- 参与集群选主
- 主节点可以管理集群状态、管理分片信息、处理创建和删除索引库的请求
data
节点的作用是什么?
- 数据的
CRUD
coordinator
节点的作用是什么?
-
路由请求到其它节点
-
合并查询到的结果,返回给用户
3.集群分布式存储
当新增文档时,应该保存到不同分片,保证数据均衡,那么coordinating node
如何确定数据该存储到哪个分片呢?
3.1.分片存储测试
插入多条数据:
测试可以看到,三条数据分别在不同分片:
3.2.分片存储原理
elasticsearch
会通过hash
算法来计算文档应该存储到哪个分片:
说明:
_routing
默认是文档的id
- 算法与分片数量有关,因此索引库一旦创建,分片数量不能修改!
新增文档的流程如下:
解读:
- 1)新增一个
id
=1的文档 - 2)对id做
hash
运算,假如得到的是2,则应该存储到shard-2
- 3)
shard-2
的主分片在node3
节点,将数据路由到node3
- 4)保存文档
- 5)同步给
shard-2
的副本replica-2
,在node2
节点 - 6)返回结果给
coordinating-node
节点
4.集群分布式查询
elasticsearch
的查询分成两个阶段:
-
scatter phase
:分散阶段,coordinating node
会把请求分发到每一个分片 -
gather phase
:聚集阶段,coordinating node
汇总data node
的搜索结果,并处理为最终结果集返回给用户
5.集群故障转移
集群的master
节点会监控集群中的节点状态,如果发现有节点宕机,会立即将宕机节点的分片数据迁移到其它节点,确保数据安全,这个叫做故障转移。
1)例如一个集群结构如图:
现在,node1
是主节点,其它两个节点是从节点。
2)突然,node1
发生了故障:
宕机后的第一件事,需要重新选主,例如选中了node2
:
node2
成为主节点后,会检测集群监控状态,发现:shard-1
、shard-0
没有副本节点。因此需要将node1
上的数据迁移到node2
、node3
: