1. 搜索系统概述

1.1 搜索系统的基本组成

一个完整的搜索系统由四个核心层构成,它们协同工作,将用户查询转化为精准、有序的结果。

层级 核心组件 职责说明
数据采集层 爬虫 / 数据管道 / 连接器 从数据库、文件系统、API 或网页获取原始数据,并解析为结构化文档。
索引构建层 分词器 / 倒排索引构建器 / 存储引擎 对文档进行分词、过滤、归一化,生成倒排索引并持久化到磁盘或内存。
查询解析层 查询分析器 / 重写器 / 评分器 接收用户输入,进行分词、纠错、同义词扩展,生成可执行的查询树。
结果返回层 检索器 / 排序器 / 摘要生成器 在索引中查找匹配文档,按相关性(BM25、向量相似度)排序,返回高亮摘要。
架构要点: 数据采集与索引构建属于“写入路径”,查询解析与结果返回属于“读取路径”。实时与近实时架构的核心差异,就在于写入路径的延迟控制策略。

1.2 索引与查询的核心概念

理解搜索系统,必须掌握两个基础概念:倒排索引 和 查询评分。

  • 倒排索引(Inverted Index):以词项为键,记录每个词项出现在哪些文档(Doc ID)及出现位置(Position)。这是搜索系统实现快速全文检索的基石。
  • 段(Segment):索引的最小独立单元。每个段是一个不可变的倒排索引文件。新文档先写入内存缓冲区,刷新(Flush)后生成一个新段。
  • 提交(Commit):将内存中的段持久化到磁盘,并更新全局提交点。提交后的段对查询可见。
  • 查询评分(Scoring):检索到匹配文档后,使用 TF-IDF、BM25 或向量距离算法计算相关性分数,按分数降序返回。
// 倒排索引简化示例(词项 → 文档列表)
"搜索"   →  Doc1:pos[3,7], Doc3:pos[1]
"索引"   →  Doc1:pos[5],   Doc2:pos[2,9]
"架构"   →  Doc2:pos[4],   Doc3:pos[6]
关键理解: 索引的“可见性”决定了搜索结果的时效性。一个文档从写入到出现在搜索结果中,中间经历的延迟就是“索引延迟”,也是区分实时与近实时的核心指标。

1.3 实时与近实时的定义

在搜索架构语境下,“实时”与“近实时”描述的是从数据写入到查询可见的时间窗口。

特性 实时搜索(Real-Time) 近实时搜索(Near Real-Time)
延迟目标 < 100ms(通常 < 10ms) 秒级(通常 1s ~ 60s)
写入路径 直接写入内存索引,立即可见 写入缓冲区,定期刷新为段
持久化 异步或依赖 WAL(Write-Ahead Log) 定期提交到磁盘
典型场景 监控告警、日志实时分析、金融行情 电商搜索、内容平台、文档检索
一致性模型 最终一致性(允许少量丢失) 最终一致性(保证持久化)
常见误区: “实时”不等于“强一致性”。实时搜索通常牺牲部分持久化保证来换取极低延迟;近实时搜索则通过批量刷新来平衡写入吞吐与查询可见性。两者都是最终一致性模型,只是延迟窗口不同。

1.4 索引延迟与查询可见性

下图展示了从文档写入到查询可见的完整路径,清晰标出实时与近实时架构的延迟分界点。

索引延迟路径:实时 vs 近实时 数据源 内存缓冲区 实时索引 查询可见 实时路径:< 100ms 段(Segment) 磁盘提交 查询可见 近实时路径:秒级延迟 说明: 实时路径:文档直接写入内存索引,立即对查询可见,但未持久化到磁盘。 近实时路径:文档先进入缓冲区,定期刷新为段并提交到磁盘后,才对查询可见。

1.5 实时与近实时的架构权衡

选择实时还是近实时架构,本质是在延迟、吞吐、持久化、查询性能之间做权衡。

  • 实时架构优势:数据秒级可见,适合监控、风控、实时推荐等场景。
  • 实时架构代价:内存消耗高,写入路径复杂,故障恢复时可能丢失未持久化的数据。
  • 近实时架构优势:写入吞吐高,磁盘持久化保证数据安全,段合并优化查询性能。
  • 近实时架构代价:存在秒级延迟窗口,不适合对时效性要求极高的场景。
架构决策原则: 如果业务允许 1~5 秒的延迟,优先选择近实时架构(如 Elasticsearch 的 refresh_interval=1s);如果必须毫秒级可见,则需引入实时索引引擎(如 Apache Druid 或自研内存索引),并配套 WAL 保证数据不丢。