之前介绍了一个分片即一个Lucene 索引 ,一个Elasticsearch索引即一系列Lucene分片的集合。 你的应用程序与索引进行交互Elasticsearch 帮助你将请求路由至相应的分片。
为啥需要扩容呢
当我们设置某个索引的分片数量的时候使用这样的api来设定,代表有一个主分片,0套副本分片。也就是说当这一个分片宕机,意味着检索的不可用。
PUT /index
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
}
}
当每天的数据量随着日志文件的堆积,es中的数据变得越来越庞大,一个节点再也承受不了我们的流量。 我们需要添加一个节点,水平扩展来提升我们的负载。然而只有一个主分片的话,就算是新加入节点也不会自动平移到第二个节点上,解决方案只有重建索引;这就是事后应对方案了。所以我们在事前就应该作出预分配,这样来应对未来的调整,虽然在单节点一个索引多个分片 代理了存储的消耗还有检索的消耗,但是对于扩容有着天然的优势,如果我们在建立索引的时候预分配了2个主分片,这样呢当新加入节点的时候,就会把其中一个分片自动平移到另一个节点上。在 Elasticsearch 中新添加的索引默认被指定了五个主分片。 这意味着我们最多可以将那个索引分散到五个节点上,每个节点一个分片。 它具有很高的处理能力,还未等你去思考这一切就已经做到了!不过这里就提出了一个脑裂的问题,可能会出现多个小集群。这样数据完整性就无法得到保证。所以ES规定了当一个集群能够对外提供访问的前提是,可以提供访问的节点的数目超过集群总数的半数+1;discovery.zen.minium_master_nodes=6
对于集群而言,是否是分片越多越好呢,这一点肯定不是越多越好,为什么讲呢,一个分片并不是没有代价的。首先一个分片的底层即为一个 Lucene 索引,会消耗一定文件句柄、内存、以及 CPU 运转。还有就是多分片来讲对于检索也是限制,需要扫描所有的分片。
如何选择容量呢
一个太少10000个有太多,需要多少分片呢? 一般情况下这是一个无法回答的问题。因为实在有太多相关的因素了:你使用的硬件、文档的大小和复杂度、文档的索引分析方式、运行的查询类型、执行的聚合以及你的数据模型等等,说特么一堆废话,还得是根据实际的使用场景来进行计算
- 基于你准备用于生产环境的硬件创建一个拥有单个节点的集群。
- 创建一个和你准备用于生产环境相同配置和分析器的索引,只有一个主分片无副本分片。
- 索引实际的文档(或者尽可能接近实际)。
- 运行实际的查询和聚合(或者尽可能接近实际)
这样就得到了单个分片的数据容量,用需要索引的数据总数加上一部分预期的增长,除以单个分片的容量,结果就是你需要的主分片个数,这是在所有节点机器配置以及网络环境一致的理想估算值。
副本
什么是副本,在分布式系统中,副本就是为了提神系统吞吐量和数据完整性上提出的一种产物,而且在es当中,这个副本策略是通过API动态设置的,然后集群内部平滑伸缩。如下图所示的集群中有3个节点一个索引具有3个主节点的和一套副本。
PUT /blogs/_settings
{
"number_of_replicas" : 2
}
这样集群对外提供检索能力的节点就伸缩到9个,在光主分片的效果上提神了3倍。
在索引写入时,副本分片做着与主分片相同的工作。新文档首先被索引进主分片然后再同步到其它所有的副本分片。增加副本数并不会增加索引容量。
在索引检索时,如果你的索引也如常见的那样是偏向查询使用的,那你可以通过增加副本的数目来提升查询性能,但也要为此 增加额外的硬件资源。
主分片和副本分片如何交互
写操作
新建、索引和删除 请求都是 写 操作, 必须在主分片上面完成之后才能被复制到相关的副本分片。
- 客户端向 Node 1 发送新建、索引或者删除请求。
- 节点使用文档的 _id 确定文档属于分片 0 。请求会被转发到 Node 3,因为分片 0 的主分片目前被分配在 Node 3 上。
- Node 3 在主分片上面执行请求。如果成功了,它将请求并行转发到 Node 1 和 Node 2 的副本分片上。一旦所有的副本分片都报告成功, Node 3 将向Master节点报告成功,Master节点向客户端报告成功。
在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。
检索操作
可以从主分片或者从其它任意副本分片检索文档,在处理读取请求时,Master在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。
1、客户端向 Node 1 发送获取请求。
2、节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到 Node 2
3、Node 2 将文档返回给 Node 1 ,然后将文档返回给客户端。