20.2 近实时索引、同步、分片与搜索运维
搜索索引通常是权威数据库的派生视图。它可以短暂陈旧、可以重建,却不能悄悄成为库存、价格或权限的第二个裁判。
近实时来自 Refresh,不是写入失败
Lucene 以不可变 segment 组织索引。新文档先进入内存索引结构与日志路径,refresh 打开新的可搜索 segment;后台 merge 再把小 segment 合并。
Elasticsearch 的 index API 返回成功后,文档不一定立刻能被 search API 命中。默认 refresh 行为依部署与索引活跃状态而异,不能把“永远 1 秒”写死。需要 read-after-write 搜索体验时,可评估 refresh=wait_for,让写请求等待下一次自然 refresh;频繁强制 refresh=true 会制造大量小 segment 并增加 merge 成本。
还要区分:
- refresh:让最近操作可搜索;
- flush:推进持久化边界并处理 translog/commit 相关状态;
- merge:合并不可变 segment,清理已删除文档的物理占用;
- replica acknowledgement:决定索引写入的副本确认条件。
它们不是同一个“刷盘”动作。
Primary Shard 决定数据切分
文档 ID 或 routing 值映射到 primary shard,副本 shard 保存该 primary 的复制数据。搜索请求由 coordinating node 发往相关 shard copy,再合并各 shard 的 top results。
query
-> shard 0 top-k
-> shard 1 top-k
-> shard 2 top-k
-> coordinator merge/rerankPrimary shard 太少会限制并行与容量,太多则增加 heap、文件句柄、cluster state、scatter/gather 和恢复成本。副本提高故障容忍与潜在读吞吐,不会增加写入数据的分片数。
自定义 routing 可让同一租户/实体查询只访问部分 shard,却也可能制造热点和超大 shard。规划应使用真实文档大小、查询 fan-out、恢复时间和增长曲线,而不是固定“每 shard 多少 GB”的万能数字。
数据库到搜索索引的同步
可靠链路通常是:
database transaction
-> outbox/WAL/CDC
-> durable event log
-> idempotent indexer
-> search index
-> checkpoint + lag metrics事件至少携带稳定实体 ID、source version 和删除语义。Indexer 对同一实体乱序事件应拒绝旧版本覆盖新版本;删除不能只从源表缺席推断,应传播 tombstone 或显式删除事件。
周期全量同步容易在扫描期间混入增量,造成缺口或倒退。正确重建需要一致快照位置:先记录/取得快照对应的 WAL/offset,再回填快照,最后从衔接位置消费增量。
Reindex 用新索引和 Alias 切换
修改 analyzer、字段类型或主分片规划时,通常创建新版本索引:
products-v3 (current alias target)
products-v4 (backfill + catch up + verify)流程:
- 创建显式 mapping/settings 的 v4;
- 从一致快照全量回填;
- 追上增量并记录 checkpoint;
- 对比数量、抽样文档、过滤和相关性;
- 原子切换读写 alias;
- 保留可回退窗口,再删除 v3。
双写 v3/v4 仍需处理一边成功一边失败;基于同一 CDC 日志分别投影通常更容易重放和审计。
搜索结果不能直接裁决交易
用户在搜索页看到“有库存”,点击下单时必须回权威交易库重新校验并原子扣减。权限撤销若要求立即生效,也不能只等待索引 refresh。
搜索服务应声明 freshness SLO,例如:
- 99% 商品更新在 30 秒内可搜;
- 删除/下架在 10 秒内从公共结果移除;
- 权限强校验在返回详情或执行操作时由权威服务完成。
不同字段可有不同风险与降级路径。
深分页与结果一致性
from + size 越深,每个 shard 需要保留并返回更多候选,协调节点成本迅速增加。面向滚动列表优先使用 search_after 和稳定 tie-breaker;需要跨多页保持一致视图时结合 point in time(PIT)。
排序字段必须稳定且确定。只按分数时,相同分数文档在 refresh、replica 或 shard 状态变化后可能换序。
词法、向量与混合检索
向量检索擅长语义相似,却不天然保证精确编号、否定词、最新事实或权限过滤。词法检索擅长精确 term 与可解释过滤。混合检索通常:
lexical candidates + vector candidates
-> normalize / RRF / learned reranker
-> hard business filtersEmbedding 模型版本应写入索引元数据;升级模型往往需要重新计算向量和评估。向量召回同样需要离线 judgement、延迟和内存/磁盘成本测试,不能只看几条演示查询。
运维指标
至少监控:
- indexing rate、reject、bulk error 与 CDC lag;
- refresh、segment count、merge time/throttle;
- shard size、allocation、recovery 与 cluster health;
- search p50/p95/p99、timeout、cancel 和 shard failures;
- query fan-out、slow log、cache 与 heap/GC;
- zero-result rate、Recall/nDCG 采样与权限漏出检查;
- source version 与 index checkpoint 差距;
- 全量重建和 alias 回退耗时。
集群绿色只说明 shard 分配状态,不证明数据已与权威源同步,也不证明搜索质量正确。
参考
- Elasticsearch:Refresh API
- Elasticsearch:Search Shard Routing
- Elasticsearch:Index Statistics
- Lucene:BM25Similarity
至此,第五卷的专业主线从关系模型一直延伸到缓存与搜索派生视图。下一阶段的全卷校验将检查代码、链接、目录和术语,再进入故事线与文风统一。