索引与分片设计实践

索引与分片设计实践 #

这篇更偏“工程实践”:不讲所有细节,只给你一套在大多数场景下都靠谱的索引设计思路,帮你少走弯路。

1. 先确定“索引边界”,再谈分片 #

思考顺序建议是:

  1. 这一坨数据是否应该是一个索引
    • 典型边界:数据生命周期、访问模式、隔离需求(权限/多租户)、硬件拓扑(可用区)
  2. 在它内部,需要多少主分片、多少副本?

常用的索引边界模式:

  • 按业务域:ordersproductslogs_applogs_security
  • 按时间:logs-2026.02.01logs-2026.02.02(时间序列,见数据建模章节)
  • 按租户/大客户:大客户单独索引,小客户共享索引(见多租户建模章节)

建议:先控制“索引颗粒度”合理,再通过分片做水平扩展;不要指望一个索引撑住所有业务。

2. 分片与副本:从“目标分片大小”倒推 #

分片设计没有万能数字,但可以从一个直觉出发:希望单个分片的大小 & 负载落在一个可控区间内。实践中常见的经验值:

  • 单分片 10–50GB 对大多数场景比较健康(结合你的磁盘/快照策略微调)
  • 对于热点写入较猛的日志类索引,可以略小一点,便于滚动与恢复

一个简单的倒推流程:

  1. 用测试环境或历史数据估算:一个分片大概能承载多少数据 & QPS(参考“容量规划”章节)
  2. 预估未来一段时间的索引规模(例如:单日日志量、订单增长等)
  3. 总数据量 / 目标分片大小 ≈ 主分片数 算一个初始值,再按机器数/故障域稍微调整

副本数则更多取决于:

  • 可用性(能容忍多少节点故障)
  • 读流量(读多写少时可以多一点副本当读节点)

生产上常见组合:

  • 写多读少:number_of_replicas = 0/1
  • 读多写少:number_of_replicas = 1+,甚至为查询集群设独立的 follower

3. 时间序列:按时间切索引,而不是疯狂加分片 #

日志、指标、行为埋点这些“时间序列”场景,最容易踩坑的设计就是:

一个索引,分片拉满,想靠加分片吃下所有历史。

更推荐的做法:

  • 按时间切索引:天/周/月(logs-2026.02.01 之类)
  • 用别名组织“当前/最近 N 天/全部”视图:
    • logs_current → 指向当天索引
    • logs_last_7d → 指向最近 7 个索引
  • 数据退役时,按索引维度做:
    • flush + close(冷数据仍保留)
    • snapshot + delete(非常老的数据)

好处:

  • 清理和归档成本都在“索引级别”,而不是“逐文档删除”
  • 不需要在单索引内搞海量分片,恢复和迁移更安全

4. 多租户:一索引一大户,多小户共索引 #

多租户设计常见两极:

  • 一租户一索引:隔离性好,适合少数大客户(数据量/查询压力足够大)
  • 多租户共索引:通过字段 + routing + 查询过滤隔离,适合大量小客户

一个折衷方案:

  • 为“大租户”单独建索引(甚至单独集群)
  • “长尾小租户”共享一个或少数几个索引,通过 tenant_id 字段 + alias/routing 做隔离

索引与分片设计时需要考虑:

  • 是否需要“搬家”能力(从共享索引迁出到独立索引)
  • tenant_id 是否作为 routing key(让同一租户数据尽量落在同一分片)

具体建模细节可参考数据建模章节的“多租户”部分。

5. 零停机演进:新索引 + 重建 + 别名切换 #

索引设计从来不是“一步到位”,业务演进到一定阶段,你几乎必然会遇到:

  • 字段类型要改(textkeyword,数值精度调整)
  • 分析器要换(分词策略、同义词、归一化规则)
  • 分片数要调整(原来的扩展因子不够用了)

这类变更不能在原索引上“硬改”,推荐统一走这条路线:

  1. 设计并创建新索引(my_index_v2),带上新 Mapping 与 settings
  2. _reindex 或 scroll + bulk 从旧索引迁移数据
  3. 用别名原子切换:
    • my_indexmy_index_v1 移除
    • my_index 新增指向 my_index_v2

示意(别名切换):

POST /_aliases
{
  "actions": [
    { "remove": { "index": "my_index_v1", "alias": "my_index" }},
    { "add":    { "index": "my_index_v2", "alias": "my_index" }}
  ]
}

要点:

  • 应用层只使用别名,不直接写死真实索引名
  • 重建过程中可以双写/只读/灰度切换,具体策略根据业务而定

6. 索引与分片设计的一点 Checklist #

  • 这一坨数据是不是应该拆成多个索引?(按业务域 / 时间 / 租户)
  • 单分片目标大小大致是多少?(结合存储和恢复策略)
  • 主分片数与副本数是如何依据容量 & HA 要求确定的?
  • 是否为时间序列/多租户场景选用了合适的模式?
  • 是否已经预留了“新索引 + 重建 + 别名切换”的演进路线?

下一步可以继续阅读:

参考手册(API 与参数) #

本篇更多讲的是“怎么设计”,如果你需要查具体的 API 与参数,可以参考: