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 索引延迟与查询可见性
下图展示了从文档写入到查询可见的完整路径,清晰标出实时与近实时架构的延迟分界点。
1.5 实时与近实时的架构权衡
选择实时还是近实时架构,本质是在延迟、吞吐、持久化、查询性能之间做权衡。
- 实时架构优势:数据秒级可见,适合监控、风控、实时推荐等场景。
- 实时架构代价:内存消耗高,写入路径复杂,故障恢复时可能丢失未持久化的数据。
- 近实时架构优势:写入吞吐高,磁盘持久化保证数据安全,段合并优化查询性能。
- 近实时架构代价:存在秒级延迟窗口,不适合对时效性要求极高的场景。
架构决策原则: 如果业务允许 1~5 秒的延迟,优先选择近实时架构(如 Elasticsearch 的 refresh_interval=1s);如果必须毫秒级可见,则需引入实时索引引擎(如 Apache Druid 或自研内存索引),并配套 WAL 保证数据不丢。