在企业级搜索架构中,唯一不变的就是“变化”。随着业务发展,我们经常面临这样的需求:修改索引的分片数(Shards)、调整字段类型(Mapping)、开启 Easysearch 特有的 ZSTD 压缩以节省成本,甚至是将底层引擎从旧版 Elasticsearch 迁移到 Easysearch。
在传统做法中,修改索引结构通常意味着:停机 -> 重建索引 -> 导数据 -> 修改代码配置 -> 重启服务。这对于 7x24 小时运行的核心业务是不可接受的。
今天,我们将介绍 Easysearch 的“索引别名(Index Aliases)”机制,它就像 DNS 之于 IP 地址,接口之于实现类,是你构建高可用、零停机架构的“解耦神器”。
一、 为什么必须使用别名? #
在 Easysearch 中,别名(Alias) 是一个指向一个或多个索引的“软链接”。
如果你的业务代码直接写死了索引名称(例如 order_index_v1),那么当你需要优化结构创建 order_index_v2 时,就必须修改代码并重启。
最佳实践原则:
永远不要在业务代码中直接使用物理索引名称,始终使用别名。
业务程序只认 order_search(别名),至于背后是 order_v1 还是 order_v2,完全由运维在 Easysearch 侧动态控制,业务端无感知。
二、 核心实战:零停机索引重构(Blue/Green 部署) #
假设你正在使用 Easysearch,现有的索引 user_logs_v1 未开启压缩,存储占用较高。现在的目标是:创建一个开启 ZSTD 压缩的新索引 user_logs_v2,并将流量无缝切换过去。
第一步:当前状态 #
应用正在读写别名 user_logs,它指向物理索引 user_logs_v1。
GET _alias/user_logs
{
"user_logs_v1": {
"aliases": {
"user_logs": {}
}
}
}
第二步:创建新索引(Blue/Green) #
创建优化后的新索引 user_logs_v2,开启 Easysearch 的 ZSTD 压缩(codec: ZSTD)以减少存储空间。
PUT user_logs_v2
{
"settings": {
"index.codec": "ZSTD",
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
// ... 最新的 Mapping 定义
}
}
第三步:数据迁移(Reindex) #
使用 Reindex API 将数据从 v1 迁移到 v2。Easysearch 的 Reindex 效率很高,且支持异步执行。
POST _reindex?wait_for_completion=false
{
"source": {
"index": "user_logs_v1"
},
"dest": {
"index": "user_logs_v2"
}
}
第四步:原子切换(关键步骤) #
这是实现“无感”的核心。我们需要在一个原子操作中,将别名从 v1 移除,并指向 v2。
注意:千万不要先删除别名再添加,那样中间会有几十毫秒的“服务真空期”导致报错。必须使用 _aliases 接口的 actions 列表。
POST _aliases
{
"actions": [
{
"add": {
"index": "user_logs_v2",
"alias": "user_logs"
}
},
{
"remove": {
"index": "user_logs_v1",
"alias": "user_logs"
}
}
]
}
结果:对于应用程序而言,它一直在向 user_logs 读写,完全不知道底层存储已经从未压缩的 v1 变成了高效压缩的 v2。
三、 进阶场景:读写分离与滚动管理 #
对于日志类或时序数据,别名的玩法更加高级。我们可以利用别名实现读写分离。
1. 滚动写入(Rollover) #
通常我们需要一个指向“当前活跃索引”的别名用于写入(如 logs_write),和一个指向“所有历史索引”的别名用于查询(如 logs_read)。
# 初始化:logs_write 指向 logs-000001
# 所有的 logs-* 都拥有 logs_read 别名
POST logs_write/_rollover
{
"conditions": {
"max_age": "7d",
"max_docs": 10000000,
"max_size": "50gb"
}
}
当满足条件时,Easysearch 会自动创建 logs-000002,并将 logs_write 别名指向它,实现自动滚动。
2. 跨集群迁移(利用 Gateway) #
如果你正在从 Elasticsearch 迁移到 Easysearch,或者进行跨集群升级,INFINI Gateway 配合别名是绝佳组合。
你可以在 Gateway 层设置别名路由,将发往旧集群的请求,通过流量双写或灰度切分的方式,逐步引入 Easysearch 集群,实现应用层的完全无感迁移。
四、 常用别名管理命令速查 #
在日常运维中,这几个 DSL 命令非常高频:
1. 查看某个别名指向了哪些索引:
GET _alias/my_app_alias
2. 批量给多个索引添加别名(支持通配符):
例如,给所有 2023 年的日志添加 archive_2023 别名:
POST _aliases
{
"actions": [
{
"add": {
"index": "logs-2023*",
"alias": "archive_2023"
}
}
]
}
3. 利用别名进行视图过滤(Filter Alias):
这是一个被低估的功能。你可以创建一个带过滤条件的别名,让业务方只能查看到特定数据,起到权限隔离的作用。
POST _aliases
{
"actions": [
{
"add": {
"index": "users",
"alias": "active_users",
"filter": {
"term": {
"status": "active"
}
}
}
}
]
}
当用户搜索 active_users 时,Easysearch 会自动强制加上 status=active 的过滤条件。
五、 避坑指南 #
- 别名不能与索引同名:如果已经存在一个物理索引叫
products,你不能再创建一个叫products的别名。这也是为什么建议物理索引带版本号(_v1)或日期后缀的原因。 - 写入限制:如果一个别名指向了多个索引,你不能直接向该别名写入数据(Easysearch 不知道该往哪个物理索引写)。除非显式指定
is_write_index: true属性。 - 清理旧数据:在完成
v1->v2的切换并观察一段时间(如24小时)确认无误后,记得删除旧的v1索引以释放磁盘空间。
结语 #
在 Easysearch 的使用中,“索引别名”是区分新手与专家的分水岭之一。
通过合理使用别名,你不仅获得了架构上的灵活性,还能充分利用 Easysearch 的 ZSTD 压缩、分片调整等特性不断优化底层存储,而这一切对上层业务都是透明的。
从今天起,检查你的代码配置,把那些写死的索引名,都换成别名吧!





