相信读者创建index的时候,一定曾经纠结过分片数应该分配多少。笔者从实用角度来讲述一下index分片数量的选择,index分片数量严格来说不能过多,也不能过少,还要兼顾分片平衡以及集群压力。现在从一些角度来讲主分片数应该怎么选择。
分片数量与节点数(或机器数)的平衡
分析:若一个es集群的节点数为3,则考虑业务扩展(无论是容量还是其它),可能需要新增1个节点共4个节点,可能用于正常增长;有时需要新增2台(共5个节点)或者3台机器(共6个节点),可能是新功能导致数据增加很多;甚至是业务猛增,需要直接扩容5个节点(共8个节点)。考虑扩展因素,要使得index与节点数量较为均衡,正好为3、4、5、6等整数倍,那么一定是其最小公倍数30个数据分片。有的读者会问若是7个节点、8个节点、9个节点呢?这就要考虑扩容场景,一般来讲,正常扩容3到4个节点还是比较常见的,若是数据猛增,一定不仅仅是扩容两个节点总共5个节点,往往是直接翻倍扩容为6个节点,甚至将近3倍,扩容至8个节点,甚至是12个,24个分片。所以对于一个不是很大的index,容量小于500g,且考虑节点数为3,每个节点的容量为1.5T,不妨设置主分片为12,副本分片为1,共24个分片。方便以后扩展。无论是增加一个节点,还是翻倍扩容,再翻倍,都能保持分片数量是节点数的整数倍。集群压力是均衡的!
结论:
- 若index < 50g,且未来index数据肯定不会有较多增长。则可以将分片数设置为3或者6,副本分片为1
- 若index < 500g,且未来index数据会增长,但不会增长到10T量级,建议主分片数为12,副本分片数为1
- 若index容量极大,主分片可以为30、60、120。若到120,则有可能是有120个节点,若一台机器部署两个节点,则需要60台机器,相信es集群已经非常大了。这种情况最好需要业务按照业务逻辑进行拆分。
es本身的限制
因为一个分片就是一个luence,而luence的文档数限制在2g个,所以考虑到这个限制,对于文档数非常多的index,千万不能设置特别少的分片数,若超过此限制,对于集群会是灾难性的,集群会狂打异常日志,数据无法写入,导致节点所在机器因日志太多很快到100%。即使让业务停止读写,重新reindex的时间也非常久!而且机器扩展也不方便,往往最后评估处理的方案是将异常的index删除,重新创建新的index。
还有就是段文件,一个段文件不要超过20g(实际代码注释有50g限制一说),推荐一个分片能对应合并为1个段文件。这个并不是强制性的,有的index是10T的容量,却设置了10个主分片,副本分片为0,集群可以工作,但通常不建议这么做。还有一个说法是文档数不要超过1000w,主要是考虑到去query一个表,到千万级,往往性能未必能跟上。
过多的es分片会给主节点带来更多的压力,需要去维护更多分片的状态,集群压力也会因此变大,不建议创建1000个数据分片。cerebral插件观察es状态,若一个集群所有总的分片数超过1w,打开页面也会有一定的延迟,给维护带来一定困难,表现就是集群管理页面特别卡!若出现太多分片,则需要考虑降低分片数量或者拆分集群。
结论:
- 单分片文档数不能超过2g个。
- 最初规划index,单分片容量建议不超过20g,文档数不要超过1000w。
- 不建议将index数据分片设置超多。
业务请求类型场景
若业务读写请求每次能够路由到某个分片,或者绝大部分都能路由到某个片中,则index主分片数越多越好。单个节点拥有更多的分片能提升并发处理的能力,笔者曾调优过一次因为扩容导致集群处理能力并未增加,从而满足不了业务请求的案例。虽然这样,但是建议控制在120以内。若业务都是query某个条件,需要遍历查找所有分片,建议分片数不要过多,因为分片越多,拆分的子请求也越多,单个节点因拥有的分片数过多导致并发大,耗费更多的io负载和cpu负载。
集群按天、小时周期创建请求索引,推荐一个节点一个数据分片,若集群扩容或者缩容,则会导致index分片节点数量不一致,当天一定要修改分片数,确保明天的index与新扩缩容的集群的节点数是一致的即可。可能读者会疑惑为何要这么做,按天、小时创建索引,往往有如下特征:数据越旧越没价值,日志场景居多,且数据量比较多,使用query请求查询每个分片的情况居多,且一般需要保留3-7天,甚至更长。若当天扩缩容,则今天和旧的好多index就会发生分片迁移,单个index可能会导致分片不均匀,但是往往有几个旧的index一起混合分布在各个节点,平衡了集群压力,随着时间增长,旧的index一方面逐天逐小时被删除,另一方面是被读的可能性越来越小。非常常见的场景是读1小时、读3小时、读6小时、读12小时、读24小时,后面就是统计3天,统计一周的频率,最后即使是旧的index分片不均匀,读的请求越来越少, 也会随着时间的变化慢慢被删除。每个节点分配一个数据分片,能让业务query最小的分片数量,耗费更少的io和cpu。
结论:
- 业务请求若为routing字段,大部分都能路由到某个分片,以get请求居多,那么建议用较多的数据分片。
- 业务请求若为query请求,且每次都要请求每个分片,则建议一般不要超过12个分片,单节点拥有分片不建议超过3个。
- 按天、小时周期创建请求索引,一个节点一个数据分片,若扩容集群或者缩容,当时调整分片数即可。
以上就是笔者维护了诸多es集群总结的经验。这些原则并非是完全适用所有情况,但大部分情况均适用,希望大家能够用到。若是新手看着麻烦,干脆就这么记住:数据量小,主分片为6;数据量大,主分片为12;再多,可以为30!