Elasticsearch 的 routing 是什么?什么时候需要自定义 routing?
简化版
Routing 决定文档写入哪个主分片,默认根据 _id 哈希路由。自定义 routing 可以把同一租户、同一用户或同一业务键的数据放到固定分片,减少查询扇出;但也可能造成热点分片和数据倾斜。
详细版
ES 默认路由大致可理解为:
shard = hash(_routing) % number_of_primary_shards
默认 _routing 通常来自 _id。如果查询带 routing,ES 可以只查相关分片,而不是所有分片。例如多租户系统用 tenantId routing,可以让某租户查询只打到一个分片。面试要强调取舍:routing 能减少扇出,但 key 分布不均会导致热点;主分片数确定后也影响扩容和迁移。
完整版教学
一、routing 决定文档落在哪个主分片
一个索引有多个 primary shard。写入文档时,协调节点需要决定这条文档属于哪个分片。
默认情况下,ES 根据 routing 值做哈希取模。可以简化理解为:
target_shard = hash(_routing) % primary_shard_count
如果没有显式提供 routing,通常使用文档 _id 作为 routing。
记忆钩子:routing 是分片地址,不是查询过滤条件。
二、默认 routing 的好处是均匀
用 _id 哈希的好处是简单、通用,文档通常比较均匀地分散到多个主分片。
doc1 -> shard0
doc2 -> shard2
doc3 -> shard1
doc4 -> shard0
均匀分布能避免单个分片过热,也让写入和存储压力更平均。
但默认 routing 的缺点是:按业务键查询时,ES 不知道目标数据在哪个分片,可能需要查询所有分片。
三、自定义 routing 可以减少查询扇出
多租户系统中,很多查询都带 tenantId。如果写入时用 tenantId 作为 routing,查询时也带同样 routing,就能直接定位分片。
PUT /orders/_doc/1001?routing=tenant_8
{
"tenantId": "tenant_8",
"amount": 99
}
查询:
GET /orders/_search?routing=tenant_8
{
"query": {
"term": { "tenantId": "tenant_8" }
}
}
如果索引有 12 个分片,不带 routing 可能查 12 个分片;带 routing 可能只查 1 个分片。延迟和资源消耗都会降低。
四、自定义 routing 最大风险是热点和倾斜
如果某个租户特别大,用 tenantId routing 会把该租户数据全部压到一个分片上。
| routing key 分布 | 结果 | 风险 |
|---|---|---|
| 大量 key 均匀 | 分片较均衡 | 效果好 |
| 少数大 key | 某些分片巨大 | 热点和倾斜 |
| 单一 key | 全部落一片 | 基本失去分片意义 |
例如 1000 个小租户和 1 个超级租户,超级租户可能让某个分片磁盘、CPU、查询延迟都远高于其他分片。
解决方式包括大租户单独索引、routing key 加盐、按时间拆索引等。
五、routing 必须写查一致
自定义 routing 的一个坑是写入用了 routing,查询、更新、删除时忘记带相同 routing。
DELETE /orders/_doc/1001?routing=tenant_8
如果删除时不带 routing,ES 可能按 _id 默认路由去另一个分片找文档,结果找不到。查询如果不带 routing,虽然可能仍能搜到,但会退化成全分片搜索。
所以一旦使用自定义 routing,应用层要把 routing 当成文档定位协议的一部分。
六、routing 和主分片数规划有关
主分片数在索引创建后通常不能随意改变。routing 的哈希取模依赖主分片数量,所以早期规划很重要。
如果主分片太少,未来大 key 很容易打满;主分片太多,又会增加集群管理、查询扇出和小分片开销。
primary shard count = 6
routing key hash -> 0..5
自定义 routing 前要估算租户数、数据量分布、查询模式和未来增长。它是架构决策,不是单个查询参数。
七、常见误区与追问
- 误区:routing 是用来过滤数据的。 routing 只是决定分片位置,真正过滤仍靠 query。
- 误区:自定义 routing 一定提升性能。 key 分布不均会导致热点分片,性能可能更差。
- 误区:写入带 routing,查询可以随便不带。 不带会增加分片扇出,更新删除还可能找不到目标文档。
- 追问:多租户为什么适合 routing? 同租户查询集中,routing 能减少分片扇出。
- 追问:大租户怎么避免热点? 大租户独立索引、routing 加盐、按时间拆分或重新规划索引。
- 追问:routing 和主分片数有什么关系? routing 哈希映射到主分片,主分片数影响数据分布和未来扩展。
八、加强记忆
routing 记成“文档的分片地址”。默认按 _id 哈希,追求均匀;自定义 routing 用业务键减少查询扇出,适合多租户、用户维度查询。但 routing key 必须分布均匀,写查删要带同一个 routing,否则会热点、查全分片或找不到文档。