1.分片和副本
1.1什么是分片
简单来讲就是咱们在ES中所有数据的文件块,也是数据的最小单元块,整个ES集群的核心就是对所有分片的分布、索引、负载、路由等达到惊人的速度。
分片是把索引数据切分成多个小的索引块,这些小的索引块能够分发到同一个集群中的不同节点。在检索时,检索结果是该索引每个分片上检索结果的合并。类似于数据库的分库分表
举例:
假设 IndexA 有2个分片,我们向 IndexA 中插入10条数据 (10个文档),那么这10条数据会尽可能平均的分为5条存储在第一个分片,剩下的5条会存储在另一个分片中。
1.2分片的基本作用
假如索引Index可能存储了超过单个节点的硬件限制的数据。例如,占用1TB磁盘空间的十亿个文档的单个索引可能不适合单个节点的磁盘,或者可能太慢而无法单独从单个节点提供搜索请求。为了解决这样的问题,Elasticsearch提供了将索引细分为多个称为碎片(Shards)的功能,创建索引的时候就可以自定义碎片shards的数量,这些碎片shards本身都是功能齐全、可以托管到集群中任何节点的独立索引(index)。碎片的分布方式和如何将其文档聚合回搜索请求都是完全由Elasticsearch管理的并且这些都是对用户透明的。
分片(将索引分为一些碎片)最主要的原因有两个:
允许平行拆分/模块化内容容量;
允许跨分片(这些碎片可能在多个节点上)分布和并行化操作,从而提高性能/吞吐量;
1.3分片的分配
已经切分为多份的索引块,索引块分发到同一个集群中的不同节点。这个把shard分发到node的过程就是分片的分配。分配的原则是主要还是基于提高读写性能,实现负载均衡,备份恢复快。
什么时候开始分片分配机制呢:
1.index的增删
2.node的增删
3.reroute操作
4.replica的设置更改
5.初始化恢复过程
1.4 分片的规则
es的分片规则主要分为以下几类:
一、负载均衡规则,从负载均衡角度出发的一些规则,常见的有:
SameShardAllocationDecider类,该决策者不允许相同分片(primary\replication)出现在相同的节点上,重写了canAllocate方法。该类也考虑到了同一物理机多个es实例的情况(es可能多个虚拟机上,多个虚拟机在一台物理机上),通过cluster.routing.allocation.same_shard.host=true(默认false)来处理该情况。判断的依据是hostname和hostaddress。
ShardsLimitAllocationDecider类,限制同一个节点上shard的数目。可以限制同一节点上的shard总数、同一节点上同一index的shard数目,分别通过index.routing.allocation.total_shards_per_node、cluster.routing.allocation.total_shards_per_node实现。index级别可以覆盖cluster级别。在elasticsearh.yml文件中配置或者用update API实时更改。默认的值是-1,代表没有任何限制。需要注意,如降低该值会导致集群强制进行分片的重新分配,在集群平衡这个过程中引发额外的负载。
AwarenessAllocationDecider类,感知分配功能。更够感知服务器、服务机架等,尽量分散存储shard。有两类参数可以使用。第一类参数举例:我们通过参数设置分组cluster.routing.allocation.awareness.attributes: rack_id,一node启动设置了node.attr.rack_id:1,另外一node(两个node不在一个机架上)启动设置了node.attr.rack_id:2,所以shard会尽量分散到不同的rack_id上。第二类参数举例:cluster.routing.allocation.awareness.attributes: zone,cluster.routing.allocation.awareness.force.zone.values: zone1,zone2 如果zone1的机器上不能容纳所有的shard,并且zone2没有启动,剩余没有分配的shard则不会进行分配(zone1过载),直到等到zone2启动才进行分配。
二、并发数量规则
ConcurrentRebalanceAllocationDecider类,rebalance并发数控制类。配置cluster.routing.allocation.cluster_concurrent_rebalance来控制,该配置运行时可变,默认值为2,如果设置为-1,则表示无限制并发。
ThrottlingAllocationDecider类,在recovery过程中,恢复分片并发数。可动态设置控制参数配置:cluster.routing.allocation.node_initial_primaries_recoveries:这个属性的默认值为4,它用来描述单个节点上允许recovery操作的初始主分片数量;cluster.routing.allocation.node_concurrent_recoveries:它的默认值是2,它用来限制单个节点上进行recovery操作的并发数。
三、条件限制规则
FilterAllocationDecider类,通过include、exclude参数(可动态设置)控制shard的节点分配。参数:index.routing.allocation.require.、index.routing.allocation.include.、index.routing.allocation.exclude.、cluster.routing.allocation.require.、cluster.routing.allocation.include.、cluster.routing.allocation.exclude.。其中require表示必须,include表示允许,exclude表示禁止。注意Cluster的设置会重载掉index的配置,意味着如果根据index的配置该shard可以分配到此node,但是cluster的配置是不允许,那么此shard将不允许。filter被应用的顺序依次为required、include、exclude。
ReplicaAfterPrimaryActiveAllocationDecider类,该类保证只会在主分片分配完毕后才开始分配分片副本。
RebalanceOnlyWhenActiveAllocationDecider类,保证该索引的所有分片都在活跃状态才能进行rebalance过程。
ClusterRebalanceAllocationDecider类,根据shard的active状态来判断是否可以执行rebalance。使用参数cluster.routing.allocation.allow_rebalance(不能动态更改)来进行判断,参数值意义:①indices_all_active:它是默认值,表示只有集群中所有的节点分配完毕,才能认定集群再平衡完成。②indices_primaries_active:这个值表示只要所有主分片分配完毕了,就可以认定集群再平衡完成。③always:它表示即使当主分片和分片副本都没有分配,集群再平衡操作也是允许的。
DiskThresholdDecider类,通过磁盘空间阈值来控制是否分配。默认该功能是关闭的,通过cluster.routing.allocation.disk.threshold_enabled属性设置为true可以打开。cluster.routing.allocation.disk.watermark.low属性允许用户指定一个百分比阈值或者绝对数值来控制何时能够进行分片分配。比如默认值是0.7,表示当可用磁盘空间低于70%时,新的分片才可以分配到该节点上。cluster.routing.allocation.disk.watermark.high属性允许用户指定一个百分比阈值或者绝对数值来控制何时需要将分片分配到其它的节点。比如默认值是0.85,表示当可用磁盘空间高于85%时,ElasticSearch会重新把该节点的分片分配到其它节点。参数可以yml文件或者api动态设置。
上述三类分配规则的java类全部继承了AllocationDeciders抽象类,该类是负责shard的分配做一个决策结果(Decision类,决策结果类。有四中类型,ALWAYS、YES、NO、THROTTLE)。定义了canRebalance方法(给定的shard routing是否可以rebalance),canAllocate方法(给定的shard routing是否可以分配到指定的node),canRemain方法,给定的shard routing是否可以继续保留在指定的node;该类所有方法默认都返回ALWAYS。
1.5分片的数量和设置
分片个数是越多越好,还是越少越好了?根据整个索引的数据量来判断。
实列场景:
如果 IndexA 所有数据文件大小是300G,改怎么定制方案了?(可以通过Head插件来查看)
建议:(仅参考)
1、每一个分片数据文件小于30GB
2、每一个索引中的一个分片对应一个节点
3、节点数大于等于分片数
根据建议,至少需要 10 个分片。
结果: 建10个节点 (Node),Mapping 指定分片数为 10,满足每一个节点一个分片,每一个分片数据带下在30G左右。
SN(分片数) = IS(索引大小) / 30
NN(节点数) = SN(分片数) + MNN(主节点数[无数据]) + NNN(负载节点数)
1.6副本知识
副本分片的主要目的就是为了故障转移,正如在 集群内的原理 中讨论的:如果持有主分片的节点挂掉了,一个副本分片就会晋升为主分片的角色。
在索引写入时,副本分片做着与主分片相同的工作。新文档首先被索引进主分片然后再同步到其它所有的副本分片。增加副本数并不会增加索引容量。
无论如何,副本分片可以服务于读请求,如果你的索引也如常见的那样是偏向查询使用的,那你可以通过增加副本的数目来提升查询性能,但也要为此增加额外的硬件资源。
拥有两个主分片,加上每个主分片的一个副本,总共给予我们四个分片:每个节点一个,如图所示 图 一个拥有两个主分片一份副本的索引可以在四个节点中横向扩展”。
图 一个拥有两个主分片一份副本的索引可以在四个节点中横向扩展