Index Template 与 Alias:零停机变更的秘诀
Index Template 与 Alias:零停机变更的秘诀
凌晨两点,索引 Mapping 有个字段类型错了,需要重建。你把旧索引删了重建,几分钟后监控告警:订单服务全线报错,ES 返回 index_not_found_exception。
"重建索引"不难,难的是让上游服务无感知地切换。这一篇讲清楚两个关键基础设施:Index Template 和 Alias——前者管"新索引长什么样",后者管"服务找不找得到新索引"。
Index Template:自动给新索引套上配置
每个运维过 ES 的人都干过这事:创建一个索引,忘记设分片数、忘记配 analyzer、忘记关掉不必要的动态映射。回头发现已经有 200 个分片散落集群,或者某个字段类型又错了。
Index Template 解决的就是"每次建索引都要手动配"的痛点——它会在索引创建时自动应用你预设的配置。
基础用法
PUT /_index_template/orders_template
{
"index_patterns": ["orders-*"],
"priority": 100,
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "5s",
"analysis": {
"analyzer": {
"ik_smart_analyzer": { "type": "custom", "tokenizer": "ik_smart" }
}
}
},
"mappings": {
"dynamic": "strict",
"properties": {
"order_id": { "type": "keyword" },
"user_id": { "type": "keyword" },
"amount": { "type": "scaled_float", "scaling_factor": 100 },
"status": { "type": "keyword" },
"created_at": { "type": "date" }
}
}
}
}
现在任何名字匹配 orders-* 的新索引都会自动套上这套配置。建索引只需要:
PUT /orders-2025-06-01
// 不需要写任何 settings 和 mappings,template 自动生效
Component Template:模板复用
多个索引共享同一套配置(比如 analyzer 配置、分片设置),可以抽成 component template:
// 基础设置组件
PUT /_component_template/baseline_settings
{
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "5s",
"codec": "best_compression"
}
}
}
// IK 分词器组件
PUT /_component_template/ik_analyzer
{
"template": {
"settings": {
"analysis": {
"analyzer": {
"ik_smart_analyzer": { "type": "custom", "tokenizer": "ik_smart" },
"ik_max_analyzer": { "type": "custom", "tokenizer": "ik_max_word" }
}
}
}
}
}
// 组合使用
PUT /_index_template/orders_template
{
"index_patterns": ["orders-*"],
"priority": 100,
"composed_of": ["baseline_settings", "ik_analyzer"],
"template": {
"mappings": { ... }
}
}
Template 优先级
一个索引名可能匹配多个 template,priority 越高越优先。如果多个 template 有冲突字段,高优先级覆盖低优先级。
PUT /_index_template/orders_log_template
{
"index_patterns": ["orders-*", "logs-*"],
"priority": 50
}
PUT /_index_template/orders_special_template
{
"index_patterns": ["orders-special-*"],
"priority": 200
}
orders-special-2025-06 同时匹配两个 template,但优先级 200 > 50,所以用 orders_special_template 的配置。
Alias:让服务永远只认一个名字
Alias(别名)是 ES 零停机切换的关键。原理很简单:
应用程序 → orders(alias) → orders_v1(实际索引)
orders_v2(新索引,准备切换)
创建与切换
// 1. 创建 v1 并绑定 alias
POST /_aliases
{
"actions": [
{ "add": { "index": "orders_v1", "alias": "orders" } }
]
}
// 2. v2 建好,数据迁完,原子切换
POST /_aliases
{
"actions": [
{ "remove": { "index": "orders_v1", "alias": "orders" } },
{ "add": { "index": "orders_v2", "alias": "orders" } }
]
}
这两个操作是原子的——不存在"alias 同时指向两个索引"或"alias 不指向任何索引"的中间状态。上游服务全程只读 orders,完全不知道底层已经换了索引。
Write Alias:读写分离
写只落到一个索引,读可以从多个历史索引一起查:
POST /_aliases
{
"actions": [
{ "add": { "index": "orders_v2", "alias": "orders_read" } },
{ "add": { "index": "orders_v1", "alias": "orders_read" } },
{ "add": { "index": "orders_v2", "alias": "orders_write", "is_write_index": true } }
]
}
写入时用 orders_write,读取时用 orders_read(同时搜 v1 和 v2)。
Filtered Alias:一个索引,多种视角
POST /_aliases
{
"actions": [
{
"add": {
"index": "orders",
"alias": "orders_paid",
"filter": { "term": { "status": "paid" } }
}
}
]
}
应用读 orders_paid 时,ES 自动叠加上 status=paid 的过滤条件,业务代码不用写。
零停机 Reindex 完整流程
把六步串起来:
# 确保 template 正确(新索引会自动套用)
PUT /_index_template/orders_template { ... }
# 创建新索引(template 自动生效)
PUT /orders_v2
# 老数据迁移
POST /_reindex?wait_for_completion=false
{
"source": { "index": "orders_v1" },
"dest": { "index": "orders_v2" }
}
# 检查 reindex 进度
GET /_tasks?detailed=true&actions=*reindex
# reindex 完成后,原子切换
POST /_aliases
{
"actions": [
{ "remove": { "index": "orders_v1", "alias": "orders" } },
{ "add": { "index": "orders_v2", "alias": "orders" } }
]
}
# 确认 v1 不再有流量后删除
DELETE /orders_v1
真实事故复盘
某电商团队修改了商品索引的 mapping,新增了一个 nested 字段。变更流程:
- 创建
products_v15,reindex 迁移数据(约 800 万条,耗时 3 小时) - 凌晨 3 点做完,准备切换 alias
- 运维执行了
DELETE /products(忘了有 alias 保护)——无事发生,因为 alias 不是索引 - 执行 alias 切换,
productsalias 从 v14 切到 v15 - 搜索服务全部正常——一根蜡烛都没灭
Alias 是 ES 运维的第一道安全网。不用 alias 就上线 = 裸奔。
总结
- Index Template 确保新建的索引自动符合规范,不会漏配分片数、忘配分词器
- Component Template 把公共配置抽出来复用,一套 analyzer 配置在所有索引间共享
- Alias 是零停机切换的核心——应用代码只认 alias 名字,底层索引随便换
- 两者配合形成闭环:Template 管"新索引怎么建",Alias 管"新索引怎么切"
一句话:新项目上线的第一天,先把 Index Template 和 Alias 配好。这两个东西花 10 分钟,能省掉未来无数个凌晨的应急。