elasticsearch--分布式原理
1、单机服务有哪些问题
单机服务性能有限
可用性差
维护不便
2、分布式的好处
高可用性:集群可容忍部分节点宕机而保持服务的可用性和数据的完整性
易扩展:当集群的性能不满足业务要求时,可以方便快速的扩容集群,而无需停止服务。
高性能:集群通过负载均衡器分摊并发请求压力,可以大大提高集群的吞吐能力和并发能力。-
3、集群环境选择
集群理论知识学习,侧重原理,因此选择本地多节点部署,根据自己情况可选择单项目启动或者多项目启动,区别在基础课程中已经讲解,不再赘述。
核心配置
- cluster.name: 集群名称,唯一确定一个集群。
- node.name:节点名称,一个集群中的节点名称是唯一固定的,不同节点不能同名。
- node.master: 主节点属性值
- node.data: 数据节点属性值
- network.host: 本节点的绑定ip,及提供服务的ip地址
- http.port: 本节点的http端口
- transport.port:9300——集群之间通信的端口,若不指定默认:9300
- discovery.seed_hosts: 节点发现需要配置一些种子节点,与7.X之前老版本:disvoery.zen.ping.unicast.hosts类似,一般配置集群中的全部节点
- cluster.initial_master_nodes:指定集群初次选举中用到的具有主节点资格的节点,称为集群引导,只在第一次形成集群时需要。
可执行以下命令启动一个9节点集群
./elasticsearch -Ecluster.name=msb_cluster -Enode.name=node1 -Enode.roles=master -Epath.data=../node1/data -Epath.logs=../node1/logs -Ehttp.port=9201 -Etransport.port=9301 -d -Ediscovery.seed_hosts=localhost:9301,localhost:9302,localhost:9303,localhost:9304,localhost:9305,localhost:9306,localhost:9307,localhost:9308,localhost:9309 -Ecluster.initial_master_nodes=node1,node2,node3 ./elasticsearch -Ecluster.name=msb_cluster -Enode.name=node2 -Enode.roles=master -Epath.data=../node2/data -Epath.logs=../node2/logs -Ehttp.port=9202 -Etransport.port=9302 -d -Ediscovery.seed_hosts=localhost:9301,localhost:9302,localhost:9303,localhost:9304,localhost:9305,localhost:9306,localhost:9307,localhost:9308,localhost:9309 -Ecluster.initial_master_nodes=node1,node2,node3 ./elasticsearch -Ecluster.name=msb_cluster -Enode.name=node3 -Enode.roles=master -Epath.data=../node3/data -Epath.logs=../node3/logs -Ehttp.port=9203 -Etransport.port=9303 -d -Ediscovery.seed_hosts=localhost:9301,localhost:9302,localhost:9303,localhost:9304,localhost:9305,localhost:9306,localhost:9307,localhost:9308,localhost:9309 -Ecluster.initial_master_nodes=node1,node2,node3 ./elasticsearch -Ecluster.name=msb_cluster -Enode.name=node4 -Enode.roles=data -Epath.data=../node4/data -Epath.logs=../node4/logs -Ehttp.port=9204 -Etransport.port=9304 -d -Ediscovery.seed_hosts=localhost:9301,localhost:9302,localhost:9303,localhost:9304,localhost:9305,localhost:9306,localhost:9307,localhost:9308,localhost:9309 ./elasticsearch -Ecluster.name=msb_cluster -Enode.name=node5 -Enode.roles=data -Epath.data=../node5/data -Epath.logs=../node5/logs -Ehttp.port=9205 -Etransport.port=9305 -d -Ediscovery.seed_hosts=localhost:9301,localhost:9302,localhost:9303,localhost:9304,localhost:9305,localhost:9306,localhost:9307,localhost:9308,localhost:9309 ./elasticsearch -Ecluster.name=msb_cluster -Enode.name=node6 -Enode.roles=data -Epath.data=../node6/data -Epath.logs=../node6/logs -Ehttp.port=9206 -Etransport.port=9306 -d -Ediscovery.seed_hosts=localhost:9301,localhost:9302,localhost:9303,localhost:9304,localhost:9305,localhost:9306,localhost:9307,localhost:9308,localhost:9309 ./elasticsearch -Ecluster.name=msb_cluster -Enode.name=node7 -Enode.roles=data -Epath.data=../node7/data -Epath.logs=../node7/logs -Ehttp.port=9207 -Etransport.port=9307 -d -Ediscovery.seed_hosts=localhost:9301,localhost:9302,localhost:9303,localhost:9304,localhost:9305,localhost:9306,localhost:9307,localhost:9308,localhost:9309 ./elasticsearch -Ecluster.name=msb_cluster -Enode.name=node8 -Enode.roles=data -Epath.data=../node8/data -Epath.logs=../node8/logs -Ehttp.port=9208 -Etransport.port=9308 -d -Ediscovery.seed_hosts=localhost:9301,localhost:9302,localhost:9303,localhost:9304,localhost:9305,localhost:9306,localhost:9307,localhost:9308,localhost:9309 ./elasticsearch -Ecluster.name=msb_cluster -Enode.name=node9 -Enode.roles=data -Epath.data=../node9/data -Epath.logs=../node9/logs -Ehttp.port=9209 -Etransport.port=9309 -d -Ediscovery.seed_hosts=localhost:9301,localhost:9302,localhost:9303,localhost:9304,localhost:9305,localhost:9306,localhost:9307,localhost:9308,localhost:9309
开发模式和生产模式
- 开发模式:开发模式是默认配置(未配置集群发现设置),如果用户只是出于学习目的,而引导检查会把很多用户挡在门外,所以ES提供了一个设置项discovery.type=single-node。此项配置为指定节点为单节点发现以绕过引导检查。
- 生产模式:当用户修改了有关集群的相关配置会触发生产模式,在生产模式下,服务启动会触发ES的引导检查或者叫启动检查(bootstrap checks)(或者叫启动检查),所谓引导检查就是在服务启动之前对一些重要的配置项进行检查,检查其配置值是否是合理的。引导检查包括对JVM大小、内存锁、虚拟内存、最大线程数、集群发现相关配置等相关的检查,如果某一项或者几项的配置不合理,ES会拒绝启动服务,并且在开发模式下的某些警告信息会升级成错误信息输出。引导检查十分严格,之所以宁可拒绝服务也要阻止用户启动服务是为了防止用户在对ES的基本使用不了解的前提下启动服务而导致的后期性能问题无法解决或者解决起来很麻烦。因为一旦服务以某种不合理的配置启动,时间久了之后可能会产生较大的性能问题,但此时集群已经变得难以维护,ES为了避免这种情况而做出了引导检查的设置。这种设定虽然增加了用户的使用门槛,但是避免了日后产生更大的问题
单节点模式
单节点启动,节点会选举自己成为active master节点,会绕过引导检查。
discovery.type: single-node
引导检查—Bootstrap Checks
在启用生产模式时,节点启动之前ES会自动对节点的相关配置逐项检查,目的是避免开发者在对其配置项不了解的前提下做出不合理的配置。如果配置不符合性能或者兼容性要求,ES会阻止服务启动以保证服务的性能和可用性。
检查项:
- 堆大小检查
- 文件描述符检查
- 内存锁检查
- 最大线程数检查
- 最大文件大小检查
- 虚拟内存检查
- 文件系统映射数检查
- 客户端JVM检查
- 串行收集器检查
- 系统调用过滤器检查
- OnError和OnOOMError检查
- 早期访问检查
- 所有权限检查
- 发现配置检查
4、主从模式
Elasticsearch为什么使用主从模式(Leader/Follower)?Elasticsearch使用的主从架构模式,其实除此之外,还可以使用分布式哈希表(DHT),其区别在于:
- 主从模式适合节点数量不多,并且节点的状态改变(加入集群或者离开集群)不频繁的情况。
- 分布式哈希表支持每小时数千个节点的加入或离开,响应约为4-10跳。
ES的应用场景一般来说单个集群中一般不会有太多节点(一般来说不超过一千个),节点的数量远远小于单个节点(只的是主节点)所能维护的连接数。并且通常主节点不必经常处理节点的加入和离开,处于相对稳定的对等网络中,因此使用主从模式。
5、节点
候选节点/投票节点(master-eligible,有时候也叫master节点)
默认情况下,master-eligible节点是那些在集群状态发布期间参与选举并执行某些任务的节点,配置了master角色的节点都是有效的投票节点,可以参与选举也可以投票
硬件要求:
CPU:高
内存:高
网络:高
存储:高
仅投票节点
配置了master和voting_only角色的节点将成为仅投票节点,仅投票节点虽然也是候选节点,但是在选举过程中仅可以投票而不参与竞选。不过仅投票节点可以同时也是数据节点,这样的话,其不具备被选举为Master的资格,但是参与投票,可以在选举过程中发挥关键票的作用。
硬件要求:
CPU:高
内存:低
网络:高
存储:高
主节点(active master)
- 避免重负载:主节点负责轻量级集群范围的操作,例如创建或删除索引、跟踪哪些节点是集群的一部分以及决定将哪些分片分配给哪些节点。拥有一个稳定的主节点对于集群健康很重要。当选的主节点拥有履行其职责所需的资源,这对于集群的健康非常重要。如果所选的主节点承载了其他任务,那么集群将不能很好地运行。避免 master 被其他任务超载的最可靠方法是将所有符合 master 的节点配置为仅具有 master 角色的专用 master 节点,使它们能够专注于管理集群。专用master节点仍将充当协调节点,将请求从客户端路由到集群中的其他节点,但是不要以负载均衡器的目的而设置候选节点。
- 一般来说,如果小型或轻负载集群的主节点具有其他角色和职责,则其可能运行良好,但是一旦您的集群包含多个节点,使用专用的主节点通常是有意义的。
- 任何不是
voting-only
的master-eligible
节点都可以被选举为active master
。 - 主节点必须有一个
path.data
目录,其内容在重启后仍然存在,就像数据节点一样,因为这是存储集群元数据的地方。集群元数据描述了如何读取存储在数据节点上的数据,因此如果丢失,则无法读取存储在数据节点上的数据。 - 高可用性 (HA) 集群需要至少三个候选节点,其中至少两个不是仅投票节点。这样即使其中一个节点发生故障,也可以保证剩下的节点能够选举出一个主节点。
硬件要求:
CPU:高
内存:高
网络:高
存储:高 但是无需 大
数据节点
数据节点保存包含已编入索引的文档的分片。数据节点处理数据相关操作,如 CRUD、搜索和聚合。这些操作是 I/O 密集型、内存密集型和 CPU 密集型的。监控这些资源并在它们过载时添加更多数据节点非常重要。
硬件要求:
CPU:高
内存:高
网络:高
存储:速度快、容量大
协调节点
- 如果主动关闭了master、data和ingest的角色配置,当前节点就剩下一个只能路由请求、处理搜索减少阶段和分发批量索引功能的仅协调节点。本质上,仅协调节点的就相当于一个智能负载均衡器。换句话说,你是没有办法配置一个不具备协调转发能力的节点的。
- 仅协调节点过多会增加集群负担,因为主节更新集群状态必须等待每个节点的确认,而仅协调节点从这个角度上讲纯粹是一种负担。数据节点可以愉快地完成转发任务。
6、ES常见模块:Mudules
Cluster
Cluster模块是Master节点执行集群管理的封装实现,管理集群状态,维护集群级(除了集群级,还有索引级分片级等级别)的配置信息。其主要功能包括:
- 管理集群状态,将新生成的集群状态发布到集群的所有节点
- 调用allocation模块执行分片分配感知,决策分片分配行为
- 在集群各个节点直接迁移分片,保证数据平衡,shard rebalance
Allocation
此模块是实现了对节点分片的分配感知策略,新节点加入离开、动态扩容都需要分片分配感知,此模块由主节点调用,常见的使用场景如:跨机架强制感知实现高可用,冷热集群架构设计等。
Bootstrap
引导检查模块,不再赘述
Ingest
预处理模块负责数据索引之前的一些预操作,比如数据类型处理、数据的结构转换等,很多场景下课替代logstash处理管道消息,Elastic认证考试考点之一。
Monitor
监控功能提供了一种方式来了解 Elasticsearch 集群的运行状况和性能
Discovery
发现模块负责管理如发现集群中新加入的节点,或者节点退出之后将状态信息移除,起作用类似于ZooKeeper。发现木块是用于elasticsearch和的内置发现模块 默认值。它提供单播发现,但可以扩展到 支持云环境和其他形式的发现
Gateway
负责说对收到Master广播下来的集群状态数据的持久化存储,并在集群完全重启时恢复他们
Indices
索引模块管理全局级索引配置,不包括索引级及索引以下级。集群启动阶段需要主副本分片恢复就是在这个模块完成的
HTTP
HTTP模块允许通过JSON over HTTP的方式访问ES的API,HTTP模块本质上是完全异步的,这一位置没有阻塞线程等待响应。使用异步通信进行HTTP的好处是解决了C10k的问题。
Transport
传输模块用于集群内部节点通信。传输模块使用TCP协议,每个节点都与其他节点维持若干个TCP长连接,通信本质也是完全异步的。
7、分片:Shard
Shard即数据分片,是ES的数据载体。在ES中数据分为primary shard(主分片)和replica shard(副本分片),每一个primary承载单个索引的一部分数据,分布于各个节点,replica为某个primary的副本,即备份。分片分配的原则是尽量均匀的分配在集群中的各个节点,以最大程度降低部分shard在出现意外时对整个集群乃至服务造成的影响。
每个分片就是一个Lucene的实例,具有完整的功能。
7.1 分片创建策略
分片产生的目的是为了实现分布式,而分布式的好处之一就是实现“高可用性”(还包括高性能如提高吞吐量等会再后面内容展开讲),分片的分配策略极大程度上都是围绕如何提高可用性而来的,如分片分配感知、强制感知等。
互联网开发没有“银弹”,分片的数量分配也没有适用于所有场景的最佳值,创建分片策略的最佳方法是使用您在生产中看到的相同查询和索引负载在生产硬件上对生产数据进行基准测试。分片的分配策略主要从两个指标来衡量:即数量和单个分片的大小。
7.1.1 分片分配策略
- ES使用数据分片(shard)来提高服务的可用性,将数据分散保存在不同的节点上以降低当单个节点发生故障时对数据完整性的影响,同时使用副本(repiica)来保证数据的完整性。关于分片的默认分配策略,在7.x之前,默认5个primary shard,每个primary shard默认分配一个replica,即5主1副,而7.x之后,默认1主1副
- ES在分配单个索引的分片时会将每个分片尽可能分配到更多的节点上。但是,实际情况取决于集群拥有的分片和索引的数量以及它们的大小,不一定总是能均匀地分布。
- Paimary只能在索引创建时配置数量,而replica可以在任何时间分配,并且primary支持读和写操作,而replica只支持客户端的读取操作,数据由es自动管理,从primary同步。
- ES不允许Primary和它的Replica放在同一个节点中,并且同一个节点不接受完全相同的两个Replica
- 同一个节点允许多个索引的分片同时存在。
7.1.2 分片的数量
- 避免分片过多:大多数搜索会命中多个分片。每个分片在单个 CPU 线程上运行搜索。虽然分片可以运行多个并发搜索,但跨大量分片的搜索会耗尽节点的搜索线程池。这会导致低吞吐量和缓慢的搜索速度。
- 分片越少越好:每个分片都使用内存和 CPU 资源。在大多数情况下,一小组大分片比许多小分片使用更少的资源。
7.1.3 分片的大小决策
- 分片的合理容量:10GB-50GB。虽然不是硬性限制,但 10GB 到 50GB 之间的分片往往效果很好。根据网络和用例,也许可以使用更大的分片。在索引的生命周期管理中,一般设置50GB为单个索引的最大阈值。
- 堆内存容量和分片数量的关联:小于20分片/每GB堆内存,一个节点可以容纳的分片数量与节点的堆内存成正比。例如,一个拥有 30GB 堆内存的节点最多应该有 600 个分片。如果节点超过每 GB 20 个分片,考虑添加另一个节点。
查询当前节点堆内存大小:
GET _cat/nodes?v=true&h=heap.current
- 避免重负载节点:如果分配给特定节点的分片过多,会造成当前节点为重负载节点
7.2 重要的配置
7.2.1 自定义属性
node.attr.{attribute}
如何查看节点属性?
GET _cat/nodeattrs?v
7.2.2 索引级配置
- index.routing.allocation.include.{attribute}:表示索引可以分配在包含多个值中其中一个的节点上。
- index.routing.allocation.require.{attribute}:表示索引要分配在包含索引指定值的节点上(通常一般设置一个值)。
- index.routing.allocation.exclude.{attribute}:表示索引只能分配在不包含所有指定值的节点上。
//索引创建之前执行 PUT <index_name> { "settings": { "number_of_shards": 3, "number_of_replicas": 1, "index.routing.allocation.include._name": "node1" } }
```json PUT index_d { "settings": { "number_of_shards": 3, "number_of_replicas": 2 } } DELETE .kibana* GET _data_stream DELETE _data_stream/* GET _cat/nodeattrs?v PUT _cluster/settings { "persistent": { "cluster.routing.allocation.awareness.attributes": "rack_id" } } DELETE index_a GET index_a/_search { "size": 20, "query": { } } GET index_a/_mapping PUT _cluster/settings { "transient": { "cluster.routing.allocation.awareness.attributes":"rack_id", "cluster.routing.allocation.awareness.force.rack_id.values":"rack1,rack2" } } PUT index_a { "settings": { "number_of_shards": 3, "number_of_replicas": 1, "index.routing.allocation.include.rack_id": "rack1,rack2" } } ```
7.2.3 集群级配置
elasticsearch修改集群范围设置提供两种方式,
- persistent:永久性修改,persistent相关的修改保存在了
/path.data/cluster.name/nodes/0/_state/global-n.st
,如果想删除设置,删除此文件即可。 - transient:集群重启后失效。
PUT _cluster/settings { "persistent": { "cluster.routing.allocation.awareness.attributes": "rack_id" } }
7.3 索引分片分配:Index Shard Allocation
7.2.1 分片均衡策略:shard rebalance
当集群在每个节点上具有相同数量的分片而没有集中在任何节点上的任何索引的分片时,集群是平衡的。Elasticsearch 运行一个称为rebalancing 的自动过程,它在集群中的节点之间移动分片以改善其平衡。重新平衡遵循所有其他分片分配规则,例如分配过滤和强制意识,这可能会阻止它完全平衡集群。在这种情况下,重新平衡会努力在您配置的规则内实现最平衡的集群。如果您使用数据层然后 Elasticsearch 会自动应用分配过滤规则将每个分片放置在适当的层中。这些规则意味着平衡器在每一层内独立工作。
cluster.routing.rebalance.enable
(动态) 为特定类型的分片启用或禁用重新平衡:
all
-(默认)允许对所有类型的分片进行分片平衡。primaries
- 只允许主分片的分片平衡。replicas
- 仅允许对副本分片进行分片平衡。none
- 任何索引都不允许进行任何类型的分片平衡。
cluster.routing.allocation.allow_rebalance
(动态) 指定何时允许分片重新平衡:
always
- 始终允许重新平衡。indices_primaries_active
- 仅当集群中的所有主节点都已分配时。indices_all_active
-(默认)仅当集群中的所有分片(主分片和副本)都被分配时。
7.2.2 延迟分配策略(默认1m):
当节点出于任何原因(有意或无意)离开集群时,主节点会做出以下反应
- 将副本分片提升为主分片以替换节点上的任何主分片。
- 分配副本分片以替换丢失的副本(假设有足够的节点)。
- 在其余节点之间均匀地重新平衡分片。
这些操作旨在通过确保尽快完全复制每个分片来保护集群免受数据丢失。即使我们在节点级别和集群级别限制并发恢复 ,这种“分片洗牌”仍然会给集群带来很多额外的负载,如果丢失的节点可能很快就会返回,这可能是不必要的
7.2.3 分片过滤:即(Shard allocation filtering),控制那个分片分配给哪个节点。
- index.routing.allocation.include.{attribute}:表示索引可以分配在包含多个值中其中一个的至少节点上。
- index.routing.allocation.require.{attribute}:表示索引要分配在包含索引指定值的节点上(通常一般设置一个值)。
- index.routing.allocation.exclude.{attribute}:表示索引只能分配在不包含所有指定值的节点上。
7.4 分片分配感知:Shard Allocation Awareness
Shard Allocation Awareness的设计初衷是为了提高服务的可用性,通过自定义节点属性作为感知属性,让 Elasticsearch 在分配分片时将物理硬件配置考虑在内。如果 Elasticsearch 知道哪些节点位于同一物理服务器上、同一机架中或同一区域中,则它可以分离主副本分片,以最大程度地降低在发生故障时丢失数据的风险。
7.4.1 启用分片感知策略
配置节点属性
node.attr.rack_id: rack1
通过以下设置告诉主节点在分配分片的时候需要考虑哪些属性。这些信息会保存在每个候选节点的集群状态信息中
PUT _cluster/settings { "persistent": { "cluster.routing.allocation.awareness.attributes": "rack_id" } }
7.5 强制感知策略:Forced awareness
默认情况下,如果一个区域发生故障,Elasticsearch 会将所有故障的副本分片分配给其他区域。但是剩余区域可能没有足够的性能冗余来承载这些分片。
为了防止在发生故障时单个位置过载,您可以设置为cluster.routing.allocation.awareness.force
不分配副本,直到另一个位置的节点可用。
7.5.1 部署强制感知策略
设置强制感知策略,告诉主节点当前通过某个属性来划分区域,并且告知区域有哪些值
cluster.routing.allocation.awareness.attributes: zone
cluster.routing.allocation.awareness.force.zone.values: zone1,zone2
8、高可用性 ★★★
高可用性即:High Availability(HA),高可用性是分布式系统架构设计的重要因素之一,简单来说,可用性越高的集群在发生意外情况(如断电、节点宕机)的时候,服务发生故障而不可用的可能性越低,也就是降低了意外情况而对整体服务产生的影响的可能性。
8.1 高可用性原理
- 通过“分布式”的概念实现多个节点的负载均衡,并且使服务具备可扩展能力。
- 通过针对分片、节点的一列策略降低单个故障点对整体服务产生的影响。
- 通过容灾机制,尽可能把故障点还原,以恢复服务的最大可用性。
8.2 ES的容灾机制
容错性可以理解系统容忍的局部发生异常情况的比率和当异常发生时自行恢复的能力。在ES
中表现为对节点宕机的处理机制。
步骤:
- Master选举:选出集群中的Leader。
- Replica容错:新的
Active Master
会将丢失的Primary的某个Replica提升为Primary。 - 尝试恢复故障节点:Master尝试恢复故障节点。
- 数据同步:Master将宕机期间丢失的数据同步到重启节点对应的分片上去,从而使服务恢复正常。
8.3 Master节点和投票节点
8.3.1 主节点职责
负责轻量级集群范围的操作,比如:
- 创建或删除索引
- 规划和执行分片策略
- 发布、修改集群状态
选择的主节点拥有履行其职责所需的资源,这对于集群的健康非常重要。如果选择的主节点被其他任务重载,那么集群将无法正常运行。避免主机因其他任务而过载的最可靠方法是将所有符合主机条件的节点配置为dedicated master
8.3.2 如何设置dedicated master
node.roles: [ master ]
8.3.3 投票节点
每个候选节点默认有选举权和被选举权,称之为投票节点。投票节点可以参加Master竞选,同时也可以参加投票。
但是有一种投票节点比较特殊,其只具备选举权而不具备被选举权,也就是“仅投票”节点,仅投票节点只能在Master选举过程中参与投票,而不能参加竞选。仅投票在某些场景下发挥着极其重要的作用:
- 当现有票数不足以选出Master的时候,充当决胜票。
- 在小型集群中仅投票节点可同时作为数据节点避免资源浪费
8.3.4 如何配置仅投票节点
node.roles: [ master, voting_only ]
8.4 高可用性集群:
高可用性的中心思想就是采取一切可能的策略,降低集群中任意一部分节点出现问题后导致服务整体不可用的概率。其包含数据的完整性,集群的存活概率以及选主等。
8.4.1 小规模集群
-
单节点集群:
一般用于学习或者开发、测试环境,不推荐在生产环境中使用单节点集群。由于集群只有单个节点,为了适应这一点,ES默认会给集群分配所有角色。单节点角色不具备高可用性,并且无法分配副本分片。为了使集群保持健康,单节点模式下创建索引,需要使用
index.number_of_replicas
设置副本数量为0。 -
两节点集群:
- 如果出于硬件成本考虑,集群中只允许有两个节点,那么一般来说最好把两个节点都设置成数据节点。您还应该通过设置索引确保每个分片都在两个节点上冗余存储。每个非可搜索快照索引上的
Number_of_replicas
为1。这是默认行为,但可能会被索引模板覆盖。Auto-expand replicas也可以达到同样的效果,但是在这么小的集群中没有必要使用这个功能。 - 推荐在两个节点之一设置
node.master: false
明确告知其不具备候选节点资格。目的是为了确定哪个节点是主节点。集群可以容忍另一个不具备候选资格的节点的丢失。如果不做此设置,这时两个节点都会具有候选资格,但是其中一个节点如果宕机,由于选主需要票数过半(票数>N/2+1),也就是票数必须是两票才能选出active master,所以会导致无法选主。此时集群无法容忍任何一个节点宕机 - 默认情况下,ES会为每个节点分配所有角色,如果手动分配角色,一般建议为每个节点分配所有角色,如果其中一个节点宕机,另一个节点可以取而代之。
- 两个节点的集群,只允许其中一个固定的节点宕机,而不是任意一个节点。因为如果允许两个节点可以独立选举,那么如果集群由于网络或者其他原因导致节点连接断开,那么两个节点没办法确定另一个节点是否是宕机了,也就是会产生所谓的”脑裂“问题,而产生多主的情况。Elasticsearch 避免了这种情况并通过不选择任何一个节点作为主节点来保护数据,直到该节点可以确保它具有最新的集群状态并且集群中没有其他主节点。这可能导致集群在连接恢复之前没有主节点。
- 如果出于硬件成本考虑,集群中只允许有两个节点,那么一般来说最好把两个节点都设置成数据节点。您还应该通过设置索引确保每个分片都在两个节点上冗余存储。每个非可搜索快照索引上的
-
三节点集群 <HA的最低配置>:
- 三节点部署:如果整个集群中所有节点一共只有三个,建议把三个节点全部部署为数据节点和候选节点。虽然active master节点一般只负责轻量级任务不做数据节点。但是通常来说三节点集群一般不会承载很大的业务量,也就不必考虑那么多了。这也是处于成本考虑不得已而为之。三节点集群的容错能力是1,即允许一台节点故障。
- 二加一部署:即两个候选节点,一个仅投票节点,若干数据节点。这种配置的最大好处就是在保证高可用的前提下性价比更高,适用于小规模集群。由于在避免脑裂的前提下,要选举出主节点的最小节点数量是3,也就是选主的必要条件是票数过半也就是2票。而候选节点一般是不负责其他的任务的,也就不会为其分配data角色,那么集群通常会出现三个节点不存放数据的局面。此时会产生造成资源浪费。因为
active master
只存在一个,另外两个master作为候选节点,在及群众仅仅是充当了负载均衡器。为了避免这种资源浪费,通常的做法是把其中一个候选节点设置为仅投票节点,即node.roles: [ data, master, voting_only ]
,此时,当前节点在选举过程中,仅有选举权而没有被选举权,这样就可以同时给他分配数据节点的角色,因为其不会被选举为active master
。三节点集群中,三个节点必须都具有master
角色,并且仅投票节点最多只能有一个。仅投票节点由叫仲裁节点
起着决胜票
的作用。
-
多节点集群
-
一旦集群增长到三个以上的节点,可以开始根据它们的职责对这些节点做职责专一化。主要根据需要配置尽可能多的数据节点、预处理节点、机器学习节点等来均衡工作负载。随着集群变大,一般建议给每个角色使用专用节点,以便为每个任务独立扩展资源。
但是,最好将集群中候选节点数量限制为三个。主节点不像其他节点类型那样扩展,因为集群总是只选择其中之一作为集群的主节点。如果有太多候选节点,那么主选举可能需要更长的时间才能完成。在较大的集群中,一般建议把候选节点设置为专用候选节点,即不分配其他角色,并避免向这些专用节点发送任何客户端请求。以免候选节点被不必要的额外工作所拖累导致集群服务不稳定。
但是可以把候选节点之一配置为仅投票节点以便它永远不会被选为主节点。例如,集群可能有两个专用的候选节点和一个既是数据节点又是仅投票的候选节点的第三个节点。这第三个仅投票节点将在Master选举中投出决胜票,但是自己永远不会被选举为active master。
-
8.4.2 大规模集群
- 单集群
- 双区集群:
- 如果集群部署在两个区域比如两个机房内,应该在每个区域中拥有不同数量的候选节点,这样在其中一个区域出现问题的时候,会增加另一个区域的存活概率。比如两个机房部署同一个集群,那么两个机房的候选节点避免相等,因为此时如果一个机房意外断电,两个机房的服务都会停止。配置单数投票节点可避免此问题。此时其中一个机房断电,服务可用的概率为50%。
- 双区集群理论上能容忍一个区域的数据丢失,但不是任意一个区域,打个比方:服务部署在两个机房,机房A和机房B,要么是仅允许A机房出现故障而不允许B机房出现故障,也就是A机房断电服务可用,但是B机房断电服务中断;要么是仅允许B机房出现故障而不允许A机房出现故障,也就是B机房断电服务可用,但是A机房断电服务中断。从高可用的角度想,我们更希望任意一个机房断电,另一个机房的服务都不受影响,但是这是不可能的。因为没有断电的机房不知道出现故障的机房是断网了还是断电了,也就不知道应该是发起独立选举还是等待下去。如果两个机房都可以独立选主,那么就无法避免脑裂,可能会产生两个机房选出active master。解决办法是在两个区域中都配置一个仅投票节点并在独立的第三个区域添加一个额外的候选节点。这样两个区域其中之一断电,额外的投票节点就可以投出关键票。这个额外的节点也叫
专用tiebreaker
节点,此节点可以用低配服务器。
- 多区集群
- 如果集群中有三个区域,那么每个区域中应该有一个候选节点。如果集群包含三个以上的区域,那么应该选择其中的三个区域,并在这三个区域中的每一个区域中放置一个候选节点。这意味着即使其中一个区域发生故障,集群仍然可以选举主节点。
- 多集群
- Elasticsearch是主从结构,主节点能管理的节点上线一般不超过一千个,如果继续增加节点,可能会导致active master不稳定,如果集群想突破集群规模带来的性能瓶颈,一般可配置多集群,利用跨集群搜索单个超大集群拆分成多个小集群(相对小,千节点级别)来完成对集群的性能扩展。
8.4.3 总结
- 集群应该至少有两个区域包含数据节点。
- 除了主分片之外,每个 不是可搜索快照索引的索引都应该有每个主分片的至少一个副本。
- 分片分配感知配置为避免将分片的所有副本集中在单个区域内。
- 集群至少有三个候选节点。这些节点中至少有两个不是仅投票节点,均衡分配在至少三个区域中。
- 客户端被配置为将其请求发送到多个区域中的节点,或者被配置为使用负载平衡器来平衡一组适当的节点之间的请求。
9、Master选举 ★★★★
9.1 设计思路
所有分布式系统都需要解决数据的一致性问题,处理这类问题一般采取两种策略:
- 避免数据不一致情况的发生
- 定义数据不一致后的处理策略
分布式一致性解读:
我们可以通过一个简单的例子解释: 假设我们有一个单节点系统,对于此示例,你可以认为我们的节点是一个只存储一个值的数据库服务器。我们还有一个客户端去向服务器发送存储的值,在单节点的时候,存的这个值很容易达成一致或者共识。但是,如果我们有多个节点,那么怎么达成共识呢?这就是分布式一致性的问题。
9.2 ES的选举算法
ES基于Bully和Paxos两种算法实现,而并非就是两种算法或之一。 ES 7.x 基于以上算法,加入了基于Raft的优化。
- Bully:Bully是Leader选举的基本算法之一,基本原理就是按照节点ID进行排序,任何时候当前Leader的节点ID都是集群中最高节点ID。该算法非常易于实现但是当Leader处于不稳定状态的时候,如因负载过重而假死,此时可能会触发选主,选出第二大ID的节点为新的Leader。ES通过推迟选举直到Master失效(Master放弃Active Master资格触发选举)来解决问题,但是会产生双主或多主(也就是脑裂)问题。
- Paxos:Paxos非常强大,在选举方面的灵活性比Bully算法有很大的优势,但是其原理非常复杂。
- Raft:Raft是一种使用较为广泛的分布式一致性的协议,在Raft中,节点可能的状态有三种:
- Leader:主节点
- Candidate:候选节点
- Follower:跟随节点
所有的节点开始都是跟随节点。如果跟随节点收不89到领导节点的信号,则他们可以成为候选节点候选节点接着请求其他节点投票节点将以他们的投票回复候选节点如果候选节点获取到大多数节点的投票,则他将会成为领导节点此过程称为Leader选举。此时,所有对系统的修改将通过Leader节点进行。任意改变将以entry的形式添加到节点的日志中。这个日志的entry此时是没有提交的,所以,它不会更新节点的值。为了提交entry,节点首先会备份至跟随节点,然后leader等待,知直到多数节点将entry写入(自己的日志),此时Leader节点将提交entry,并且节点的数据被修改,接着Leader通知其他跟随者entry已经被提交了。此时集群的系统状态称为一致的。这个过程称为日志复制
在Raft中有两个设置超时时间的地方去控制选举 选举超时: 此时间就是跟随节点等待Leader信号直到成为候选节点的时间。选举超时时间随机设置在150ms到300ms之间。当选举超时以后,跟随节点成为候选节点,然后为自己发起一轮新的选举,并且向其他节点发起投票请求。如果收到请求的节点本轮没有发出投票,则候选节点的投票。并且节点重置选举超时时间 一旦候选节点收到大多数投票,那么他将成为Leader。Leader开始对其他跟随节点发送追加entry的消息。这些消息按心跳超时指定的时间间隔发送。跟随节点接着响应每一个追加entry的消息。在选举任期持续直到跟随节点停止接收到心跳消息,并成为候选节点。 重新选举: 和Leader选举一样。要求大多数投票,保证了本期选举只能有一个Leader被选中。如果两个节点同时成为候选节点,则会发送分裂投票。 分裂投票: 两个节点在同一期间都开始选举,并且每个都在其他节点之前到达一个单一节点。此时,每个候选节点都有两票,并且本次投票无法再收到更多投票,则节点将等待新的选举并重试。
9.3 几个重要概念
9.3.1 候选节点与投票节点
- 候选节点:具备
master
角色的节点默认都有“被选举权”,即是一个候选节点。候选节点可以参与Master选举过程 - 投票节点:每个候选节点默认都有投票权,即每个候选节点默认都是一个投票节点,但如果配置了“voting_only ”的候选节点将只有选举权而没有被选举权,即仅投票节点。
9.3.2 有效选票与法定票数
- 有效选票:包括非候选节点的所有节点都会参与选举并参与投票,但是只有投票节点的投票才是有效投票。
- 法定票数:即当选Master所需的最小票数,可通过:discovery.zen.minimum_master_nodes配置,通常情况下法定票数为投票数过半(不包含一半)。为了避免平票而导致脑裂,一般候选节点数量一般设置为奇数,即便是偶数,系统默认也会阉割掉其中一个节点的投票权,以保证不出选平票或多主。
9.4 选举过程
9.4.1 节点失效监测:FaultDetection类
在源码的描述文件中有这样一段描述:
There are two fault detection processes running. The first is by the master, to ping all the other nodes in the cluster and verify that they are alive. And on the other end, each node pings to master to verify if its still alive or an election process needs to be initiated
- NodesFaultDetection:即NodesFD,用于定期检查集群中的节点是否存活。
- MasterFaultDetection:即MasterFD,作用是定期检查Master节点是否存活。
9.5 脑裂问题:
- 何为脑裂:双主或多主
- 解决办法:discovery.zen.minimum_master_nodes=N/2+1,N为有效投票节点数。
本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/p/17399613.html