大多数ElasticSearch用户在建立索引时通用会问的一个重要问题是:我须要建立多少个分片?html
在本文中, 我将介绍在分片分配时的一些权衡以及不一样设置带来的性能影响. 若是想搞清晰你的分片策略以及如何优化,请继续往下阅读.node
分片分配是个很重要的概念, 不少用户对如何分片都有所疑惑, 固然是为了让分配更合理. 在生产环境中, 随着数据集的增加, 不合理的分配策略可能会给系统的扩展带来严重的问题.安全
同时, 这方面的文档介绍也很是少. 不少用户只想要明确的答案而不只仅一个数字范围, 甚至都不关心随意的设置可能带来的问题.elasticsearch
固然,我也有一些答案. 不过先要看看它的定义和描述, 而后经过几个通用的案例来分别给出咱们的建议.分布式
若是你刚接触ElasticSearch, 那么弄清楚它的几个术语和核心概念是很是必要的.ide
(若是你已经有ES的相关经验, 能够跳过这部分)性能
假设ElasticSearch集群的部署结构以下:大数据
经过该图, 记住下面的几个定义:优化
集群(cluster): 由一个或多个节点组成, 并经过集群名称与其余集群进行区分ui
节点(node): 单个ElasticSearch实例. 一般一个节点运行在一个隔离的容器或虚拟机中
索引(index): 在ES中, 索引是一组文档的集合
分片(shard): 由于ES是个分布式的搜索引擎, 因此索引一般都会分解成不一样部分, 而这些分布在不一样节点的数据就是分片. ES自动管理和组织分片, 并在必要的时候对分片数据进行再平衡分配, 因此用户基本上不用担忧分片的处理细节.
副本(replica): ES默认为一个索引建立5个主分片, 并分别为其建立一个副本分片. 也就是说每一个索引都由5个主分片成本, 而每一个主分片都相应的有一个copy.
对于分布式搜索引擎来讲, 分片及副本的分配将是高可用及快速搜索响应的设计核心.主分片与副本都能处理查询请求, 它们的惟一区别在于只有主分片才能处理索引请求.
在上图示例中, 咱们的ElasticSearch集群有两个节点, 并使用了默认的分片配置. ES自动把这5个主分片分配到2个节点上, 而它们分别对应的副本则在彻底不一样的节点上. 对,就这是分布式的概念.
请记住, 索引的number_of_shards
参数只对当前索引有效而不是对整个集群生效.对每一个索引来说, 该参数定义了当前索引的主分片数(而不是集群中全部的主分片数).
本文中不会对ElasticSearch的副本作详细阐述. 若是想单独了解可参考这篇文章.
副本对搜索性能很是重要, 同时用户也可在任什么时候候添加或删除副本. 正如另篇文章所述, 额外的副本能给你带来更大的容量, 更高的呑吐能力及更强的故障恢复能力.
当在ElasticSearch集群中配置好你的索引后, 你要明白在集群运行中你没法调整分片设置. 既便之后你发现须要调整分片数量, 你也只能新建建立并对数据进行从新索引(reindex)(虽然reindex会比较耗时, 但至少能保证你不会停机).
主分片的配置与硬盘分区很相似, 在对一块空的硬盘空间进行分区时, 会要求用户先进行数据备份, 而后配置新的分区, 最后把数据写到新的分区上.
分配分片时主要考虑的你的数据集的增加趋势.
咱们也常常会看到一些没必要要的过分分片场景. 从ES社区用户对这个热门主题(分片配置)的分享数据来看, 用户可能认为过分分配是个绝对安全的策略(这里讲的过分分配是指对特定数据集, 为每一个索引分配了超出当前数据量(文档数)所须要的分片数).
Elastic在早期确实鼓吹过这种作法, 而后不少用户作的更为极端--例如分配1000个分片. 事实上, Elastic目前对此持有更谨慎的态度.
稍有富余是好的, 但过分分配分片倒是大错特错. 具体定义多少分片很难有定论, 取决于用户的数据量和使用方式. 100个分片, 即使不多使用也多是好的;而2个分片, 即使使用很是频繁, 也多是多余的.
要知道, 你分配的每一个分片都是有额外的成本的:
每一个分片本质上就是一个Lucene索引, 所以会消耗相应的文件句柄, 内存和CPU资源
每一个搜索请求会调度到索引的每一个分片中. 若是分片分散在不一样的节点却是问题不太. 但当分片开始竞争相同的硬件资源时, 性能便会逐步降低
ES使用词频统计来计算相关性. 固然这些统计也会分配到各个分片上. 若是在大量分片上只维护了不多的数据, 则将致使最终的文档相关性较差
咱们的客户一般认为随着业务的增加, 他们的数据量也会相应的增长, 因此颇有必要为此作长期规划. 不少用户相信他们将会遇到暴发性增加(尽管大多数甚至都没有遇到过峰值), 固然也但愿避免从新分片并减小可能的停机时间.
若是你真的担忧数据的快速增加, 咱们建议你多关心这条限制: ElasticSearch推荐的最大JVM堆空间是30~32G, 因此把你的分片最大容量限制为30GB, 而后再对分片数量作合理估算. 例如, 你认为你的数据能达到200GB, 咱们推荐你最多分配7到8个分片.
总之, 不要如今就为你可能在三年后才能达到的10TB数据作过多分配. 若是真到那一天, 你也会很早感知到性能变化的.
尽管本部分并未详细讨论副本分片, 但咱们推荐你保持适度的副本数并随时可作相应的增长. 若是你正在部署一个新的环境, 也许你能够参考咱们的基于副本的集群的设计.这个集群有三个节点组成, 每一个分片只分配了副本. 不过随着需求变化, 你能够轻易的调整副本数量.
对大数据集, 咱们很是鼓励你为索引多分配些分片--固然也要在合理范围内. 上面讲到的每一个分片最好不超过30GB的原则依然使用.
不过, 你最好仍是能描述出每一个节点上只放一个索引分片的必要性. 在开始阶段, 一个好的方案是根据你的节点数量按照1.5~3倍的原则来建立分片. 例如,若是你有3个节点, 则推荐你建立的分片数最多不超过9(3x3)个.
随着数据量的增长,若是你经过集群状态API发现了问题,或者遭遇了性能退化,则只须要增长额外的节点便可. ES会自动帮你完成分片在不一样节点上的分布平衡.
再强调一次, 虽然这里咱们暂未涉及副本节点的介绍, 但上面的指导原则依然使用: 是否有必要在每一个节点上只分配一个索引的分片. 另外, 若是给每一个分片分配1个副本, 你所需的节点数将加倍. 若是须要为每一个分片分配2个副本, 则须要3倍的节点数. 更多详情能够参考基于副本的集群.
不知道你是否有基于日期的索引需求, 而且对索引数据的搜索场景很是少. 也许这些索引量将达到成百上千, 但每一个索引的数据量只有1GB甚至更小. 对于这种相似场景, 我建议你只须要为索引分配1个分片.
若是使用ES的默认配置(5个分片), 而且使用Logstash按天生成索引, 那么6个月下来, 你拥有的分片数将达到890个. 再多的话, 你的集群将难以工做--除非你提供了更多(例如15个或更多)的节点.
想一下, 大部分的Logstash用户并不会频繁的进行搜索, 甚至每分钟都不会有一次查询. 因此这种场景, 推荐更为经济使用的设置. 在这种场景下, 搜索性能并非第一要素, 因此并不须要不少副本. 维护单个副本用于数据冗余已经足够. 不过数据被不断载入到内存的比例相应也会变高.
若是你的索引只须要一个分片, 那么使用Logstash的配置能够在3节点的集群中维持运行6个月. 固然你至少须要使用4GB的内存, 不过建议使用8GB, 由于在多数据云平台中使用8GB内存会有明显的网速以及更少的资源共享.
再次声明, 数据分片也是要有相应资源消耗,而且须要持续投入.
当索引拥有较多分片时, 为了组装查询结果, ES必须单独查询每一个分片(固然并行的方式)并对结果进行合并. 因此高性能IO设备(SSDs)和多核处理器无疑对分片性能会有巨大帮助. 尽管如此, 你仍是要多关心数据自己的大小,更新频率以及将来的状态. 在分片分配上并无绝对的答案, 只但愿你能从本文的讨论中受益.