随手一写的 number_of_shards
集群知识补齐后,老王回头检查自己的索引,发现一个尴尬的事实:商品索引 8GB 数据,他当时随手设了 5 个主分片——平均每个分片不到 2GB,全是小分片;而日志索引 200GB 只有 2 个分片,每个 100GB,单分片大到查起来费劲。分片数在建索引时定死(第 3 篇的路由公式依赖它),改不了只能 reindex。这道数学题在建库那一刻就要算对。
黄金区间:单分片 10 到 50GB
社区长期沉淀的经验区间:单个分片 10 到 50GB,20GB 左右最舒服。为什么是这个区间?两头都是成本:
分片太小,开销占比失控。每个分片是一个独立的 Lucene 实例,有自己的一套内存结构、段文件和统计信息,这些开销是固定成本。8GB 拆 5 片,每片 1.6GB,固定开销可能占到两三成——纯浪费。分片太多还有隐藏账单:查询要扇出到所有分片再归并(第 10 篇深分页的放大效应),master 要维护的分片数一多,集群状态本身都在膨胀。
分片太大,搬迁与恢复变慢。节点扩容、宕机恢复时,分片是搬运的最小单位。一个 100GB 的分片搬一次就是一次全量拷贝,恢复几小时,期间集群 yellow。小分片搬家快,故障恢复也快。
分片数怎么算
三个变量:当前数据量、未来一年数据量、节点数。算法很朴素:
第一步:预估一年后数据量,比如商品加日志 200GB
第二步:按 20-50GB 一片,定主分片数 6 个
第三步:检查与节点数的关系:3 节点 x 6 分片
每节点 2 个主分片,分布均匀
第四步:留好水平扩展余地:以后加到 6 节点
6 分片也能均匀铺开分片数选节点数的整数倍(6 对 3 节点),分布才均匀——一个 5 分片索引在 3 节点上注定有的节点扛 2 片有的扛 1 片。另外别忘了副本也占空间:1 副本意味着磁盘要备两份,容量规划乘二。
算不准怎么办:rollover 滚动索引
数据量真算不准怎么办?答案是别做一次性大索引,做滚动索引(rollover)。第 4 篇立过的版本号习惯,这里正好升级成标准玩法:
先建 product-000001,设好滚动条件
条件:文档超 1000 万条 或 体积超 50GB 或 满 30 天
写到条件触发:自动滚出 product-000002
对外永远用别名 product,感知不到切换每个滚动单元分片数固定且小,数据涨了就让单元个数涨——用「加索引」替代「改分片数」,绕开了分片数定死的限制。日志类、时序类数据(第 2 篇埋的监控日志场景)直接配 ILM 索引生命周期管理:热节点写入、温节点查询、到期自动删除,全程无人值守。老王的日志索引从 200GB 一坨改成按月滚动,单分片回到 20GB 附近,查询延迟肉眼可见地降了。
小结
分片规划三句话:单分片 10 到 50GB 是黄金区间,分片数按未来一年算且取节点数的整数倍,算不准就用 rollover 滚动加索引。分片数定死不可怕,可怕的是建库那天没算。
分片规划好了,最后一块硬骨头是数据流:MySQL 的商品数据怎么持续进 ES?双写、定时、binlog 订阅各有什么坑?下一篇讲数据同步:MySQL 到 ES 的四条路。
评论 (0)