这是《Elasticsearch 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Elasticsearch 中已有字段的类型和分词器不能直接修改。要调整 Mapping,通常需要创建新索引、迁移数据、验证一致性,再通过别名切换。
本章讲解别名、Reindex、Mapping 变更、双写、灰度切换、回滚和数据校验。
18.1 为什么需要别名
不推荐应用直接写死物理索引:
products_v1
推荐使用别名:
products_read -> products_v1
products_write -> products_v1
别名价值:
- 应用与物理索引解耦;
- 支持 Mapping 变更;
- 支持分片数调整;
- 支持灰度和回滚;
- 一个读别名可以查询多个索引;
- 写别名必须指向唯一写索引。
18.2 创建别名
创建索引时添加:
PUT /products_v1
{
"aliases": {
"products_read": {},
"products_write": { "is_write_index": true }
}
}
后添加:
POST /_aliases
{
"actions": [
{
"add": {
"index": "products_v1",
"alias": "products_read"
}
},
{
"add": {
"index": "products_v1",
"alias": "products_write",
"is_write_index": true
}
}
]
}
查看:
GET /_cat/aliases/products*?v
18.3 过滤别名
POST /_aliases
{
"actions": [
{
"add": {
"index": "products_v1",
"alias": "products_on_sale",
"filter": {
"term": { "status": "ON_SALE" }
}
}
}
]
}
查询 products_on_sale 时自动附加状态过滤。过滤别名适合逻辑视图,但权限控制仍应使用集群安全能力,而不是只依赖别名。
18.4 Reindex
创建新索引:
PUT /products_v2
{
"settings": {
"number_of_shards": 6,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
},
"brand": { "type": "keyword" },
"price": { "type": "scaled_float", "scaling_factor": 100 }
}
}
}
迁移数据:
POST /_reindex?wait_for_completion=false
{
"source": {
"index": "products_v1",
"size": 1000
},
"dest": {
"index": "products_v2"
}
}
返回任务 ID:
{
"task": "oTUltX4IQMOUUVeiohTt8A:12345"
}
查看任务:
GET /_tasks/oTUltX4IQMOUUVeiohTt8A:12345
取消任务:
POST /_tasks/oTUltX4IQMOUUVeiohTt8A:12345/_cancel
18.5 Reindex 条件与脚本
只迁移部分数据:
POST /_reindex
{
"source": {
"index": "products_v1",
"query": {
"range": {
"updated_at": { "gte": "2026-01-01" }
}
}
},
"dest": {
"index": "products_v2"
}
}
字段转换:
POST /_reindex
{
"source": { "index": "orders_v1" },
"dest": { "index": "orders_v2" },
"script": {
"source": """
ctx._source.amount = ctx._source.amount_cents / 100.0;
ctx._source.remove('amount_cents');
"""
}
}
18.6 零停机变更流程
1. 保留旧索引 products_v1 和写别名
2. 创建新索引 products_v2
3. 启动 Reindex 迁移存量
4. 开启双写或 CDC 同步增量
5. 对比 v1/v2 数量和抽样数据
6. 用读别名灰度切流量
7. 观察查询结果和性能
8. 切写别名到 v2
9. 保留 v1 一段时间用于回滚
10. 下线 v1
切换读别名:
POST /_aliases
{
"actions": [
{ "remove": { "index": "products_v1", "alias": "products_read" } },
{ "add": { "index": "products_v2", "alias": "products_read" } }
]
}
切换写别名:
POST /_aliases
{
"actions": [
{ "remove": { "index": "products_v1", "alias": "products_write" } },
{ "add": { "index": "products_v2", "alias": "products_write", "is_write_index": true } }
]
}
18.7 双写与 CDC
双写
应用写 MySQL
-> 同步写 products_v1
-> 同步写 products_v2
优点是延迟低;缺点是侵入业务、两份数据可能不一致、失败补偿复杂。
CDC
MySQL binlog -> Kafka -> Consumer
-> products_v1
-> products_v2
优点是与应用解耦、可回放、失败可重试。切换完成后只需保留 v2 消费者。
推荐策略
大多数系统推荐:
事实源 MySQL + CDC/同步服务写当前索引
Reindex 迁移存量
短窗口双写或增量追赶
别名切换
18.8 数据校验
数量:
GET /products_v1/_count
GET /products_v2/_count
按状态统计:
GET /products_v1/_search
{
"size": 0,
"aggs": {
"status": { "terms": { "field": "status" } }
}
}
抽样比较:
1. 随机取 1000 个 ID
2. 分别读取 v1/v2 文档
3. 比较关键字段和版本
4. 记录差异并修复
搜索对比:
1. 收集 100 个线上查询
2. 在 v1/v2 分别执行
3. 比较命中数、Top20、耗时
4. 人工评估差异是否合理
18.9 灰度与回滚
灰度方式:
- 内部账号先切 v2;
- 按用户百分比切;
- 按机房或服务实例切;
- 对比新旧结果;
- 监控无结果率、点击率、延迟和错误率。
回滚:
POST /_aliases
{
"actions": [
{ "remove": { "index": "products_v2", "alias": "products_read" } },
{ "add": { "index": "products_v1", "alias": "products_read" } }
]
}
如果写别名已经切到 v2,回滚前要评估切换窗口内 v2 独有数据的处理方式。
18.10 分片数调整
Reindex 适合任意调整主分片数:
products_v1: 3 shards
products_v2: 12 shards
Split API 只能增加分片数,且原分片数需满足拆分倍数要求:
POST /products_v1/_split/products_v2
{
"settings": {
"index.number_of_shards": 6
}
}
Shrink API 减少分片数:
POST /products_v1/_shrink/products_v2
{
"settings": {
"index.number_of_shards": 1
}
}
两者要求索引只读并满足分片分布条件。通用 Mapping 变更仍优先 Reindex。
18.11 变更管理清单
变更前:
- 明确目标:Mapping、分词器、分片数、索引设置;
- 评估磁盘容量;
- 准备新索引模板;
- 确认同步链路;
- 备份关键索引;
- 制定回滚方案;
- 通知业务方。
变更中:
- 低峰执行 Reindex;
- 控制任务并发;
- 观察磁盘、CPU、IO;
- 增量追赶;
- 校验数量和质量;
- 灰度切读。
变更后:
- 保留旧索引;
- 监控搜索指标;
- 确认写链路正常;
- 更新文档和监控面板;
- 到期删除旧索引。
18.12 本章小结
- 应用应使用读写别名,不直接依赖物理索引;
- Mapping 和分词器变更通常需要新索引和 Reindex;
- Reindex 建议异步执行并监控任务;
- 零停机需要存量迁移、增量追赶、校验、灰度和回滚;
- CDC 比业务双写更容易保证可回放和低侵入;
- 切换写别名前必须确认数据一致性;
- 旧索引应保留一段时间用于回滚。
18.13 思考题
- 为什么读写别名要分开?
- Reindex 期间如何处理持续更新的增量数据?
- 切换写别名前需要做哪些校验?
- 双写和 CDC 各有什么优缺点?
- 如果新索引查询结果明显变差,如何回滚和定位?