搜索流程
架构设计需兼顾海量数据处理能力 、低延迟查询响应 和结果相关性等。
数据采集
爬虫系统:从种子URL递归抓取,遵循robots 协议 (网站通过robots.txt
声明哪些内容可抓取),避免违规抓取。
数据预处理
将原始数据(如 HTML 网页)转化为结构化、可索引的内容,提升后续索引和检索效率。
- 网页解析与清洗 :
- 提取有效内容:从 HTML 中剥离标签(如
<div>
<script>
),保留文本、标题、摘要、关键词等;排除广告、导航栏等冗余信息(用规则或机器学习模型识别)。 - 处理特殊内容:对图片、视频等非文本数据,提取元信息(如图片 alt 标签、视频标题)。
- 提取有效内容:从 HTML 中剥离标签(如
- 分词(Tokenization) :
- 对文本拆分(如中文用 jieba、IKAnalyzer 分词,将 "我爱北京天安门" 拆分为 "我 / 爱 / 北京 / 天安门";英文按空格拆分),生成 "词项(Term)"。
- 处理同义词(如 "电脑"→"计算机")等,减少噪音。
- 文档去重 :
- 识别重复或高度相似的文档(如镜像网站、抄袭内容),避免索引冗余。常用方法:SimHash(将文档转化为 64 位哈希值,通过汉明距离判断相似度)。
- 标准化:统一格式(如日期 "2023-10-01""10/01/2023" 转为标准格式)、大小写转换(英文 "Apple"→"apple")。
检索索引构建
当数据量巨大时,将预处理后的内容组织成高效的数据结构(如倒排索引),支撑快速检索。
- 倒排索引:根据特征获取所有相关文档。
- 正排索引 :根据文档id快速获取其内容和特征。
- 向量索引:
- 索引存储 :
- 内存索引:小数据量场景(如实时搜索),用哈希表或平衡树存储,查询速度快。
- 磁盘索引:海量数据场景(如通用搜索引擎),用 B + 树或 Lucene 的分段索引(将索引分为多个段,支持增量更新),减少 IO 开销。
查询处理与检索模块
功能:接收用户查询,快速从索引中找到匹配的文档。
- 核心流程 :
- 查询解析 :
- 分词:对用户输入的查询词(如 "北京 旅游 攻略")进行分词,与预处理阶段保持一致(避免 "旅游" 被拆分为 "旅""游" 导致匹配失败)。
- 纠错:通过编辑距离(如 "北景"→"北京")或用户输入历史,修正拼写错误。
- 扩展:基于同义词表(如 "手机"→"智能手机")或上下文,扩展查询词(提升召回率)。
- 索引检索 :
- 基于倒排索引,快速定位包含查询词的文档(如 "北京" 对应的文档列表、"旅游" 对应的文档列表)。
- 集合运算:对多词查询(如 "北京 AND 旅游"),通过交集(AND)、并集(OR)等运算获取最终候选文档集(如用 bitmap 存储文档 ID,高效计算交集)。
- 过滤:结合元信息(如时间范围 "2023 年后"、类型 "新闻")过滤无关文档。
- 查询解析 :
结果排序与展示模块
功能:对候选文档排序(按相关性从高到低),并以友好方式展示给用户。
- 排序算法 :
- 基础相关性算法 :
- TF-IDF:词项在文档中的频率(TF)越高、在所有文档中出现的频率(DF)越低,相关性越高(如 "量子力学" 在某篇论文中高频出现,且很少出现在其他文档中,则该论文与 "量子力学" 查询相关性高)。
- BM25:优化 TF-IDF,加入文档长度归一化(避免长文档因词频高被高估)。
- 链接分析算法 :
- PageRank(谷歌核心算法):基于 "网页被越多高权重网页链接,自身权重越高" 的思想,适合网页排序(如权威新闻网站的链接比个人博客更有价值)。
- HITS:区分 "权威页"(内容质量高)和 "枢纽页"(链接多),适合特定主题查询(如学术论文)。
- 机器学习排序(Learning to Rank) :
- 基于用户行为数据(如点击率 CTR、停留时间)、文档特征(如时效性、作者权威性),训练排序模型(如 XGBoost、Transformer),动态优化排序结果(更符合用户需求)。
- 基础相关性算法 :
- 结果展示:提取文档标题、摘要(高亮显示查询词)、URL、发布时间等信息,按排序结果展示;支持分页、筛选(如按时间、类型)。
辅助模块
- 缓存系统:存储热门查询的结果(如用 Redis),减少重复检索和计算(提升响应速度,降低服务器压力)。
- 反作弊系统:识别并过滤垃圾文档(如关键词堆砌的网页)或恶意查询(如刷量)。
- 用户画像模块:基于用户历史查询、点击行为,构建用户兴趣模型(如 "喜欢科技新闻"),实现个性化推荐(如不同用户搜索 "苹果",分别展示 "水果" 或 "手机" 结果)。
向量检索
向量检索的本质是:将数据(无论结构化还是非结构化)转化为高维向量(特征向量),再通过计算向量之间的 "相似度",从向量数据库中快速找到与目标向量最相似的向量集合,最终映射回原始数据 。向量检索的核心流程依赖两个关键步骤:数据向量化 和相似度计算。
常见数据的向量化方式:
- 文本:通过词嵌入(Word2Vec、GloVe)或预训练语言模型(BERT、GPT)生成向量,向量维度通常为 768、1024 等(如 BERT-base 模型生成 768 维向量);
- 图像:通过卷积神经网络(CNN,如 ResNet、VGG)提取特征,生成向量(如 ResNet-50 生成 2048 维向量);
- 音频:通过 MFCC(梅尔频率倒谱系数)或音频模型(如 Wav2Vec)转化为向量;
- 商品 / 用户:在推荐系统中,通过协同过滤或深度学习模型生成用户 / 商品的嵌入向量(如 128 维向量)。
常用的相似度度量方法:余弦相似度、欧氏距离、曼哈顿距离、汉明距离等
构建索引:当向量数量庞大(百万 / 亿级)时,直接计算所有向量的相似度效率极低,需通过索引技术加速检索(见下文 "常用索引技术");
数据结构
倒排索引(Inverted Index)
- 地位:搜索引擎的 "基石" 数据结构,几乎所有现代搜索引擎(如 Elasticsearch、Solr、Lucene)的核心索引方式。
- 原理 :
正排索引(顺排索引)是 "文档→关键词" 的映射(如 "文档 1 包含词汇 A、B、C"),而倒排索引则反过来,是 "关键词→文档列表" 的映射(如 "词汇 A 出现在文档 1、3、5 中")。
每个关键词还会关联额外信息,如词频(TF,该词在文档中出现的次数) 、位置(该词在文档中的具体位置,用于短语匹配) 、文档频率(DF,包含该词的文档总数) 等,用于后续相关性
字典树(Trie Tree,前缀树)
- 用途 :主要用于前缀匹配(如搜索提示、自动补全)和快速判断关键词是否存在。
- 原理 :
以字符串的字符为节点构建树结构,根节点为空,每个路径代表一个字符串。例如 "apple""app""apply" 的字典树中,"app" 是前两者的公共前缀,可共享路径。 - 优势 :
查找、插入、删除的时间复杂度为 O (L)(L 为字符串长度),适合处理大量字符串的前缀匹配场景(如输入 "微" 时,提示 "微信""微博" 等)。
平衡二叉搜索树(BST)与变种
- 常见类型:红黑树、AVL 树、B 树 / B + 树等。
- 用途 :
- 用于索引的元数据管理(如文档 ID 与路径的映射)。
- B 树 / B + 树因适合磁盘存储(减少 IO 次数),常被用于数据库索引(搜索引擎的底层存储可能依赖数据库),或对倒排索引中的词项进行排序和快速查找。
- 优势 :
保证查找、插入、删除的高效性(平均 O (logN)),且 B + 树的叶子节点有序且相连,支持范围查询(如 "查找包含关键词 A 且发布时间在 2023-2024 的文档")。
哈希表(Hash Table)
- 用途 :用于精确匹配查询(如通过文档 ID 快速定位文档内容)或缓存常用数据(如热门关键词的倒排表)。
- 原理 :
通过哈希函数将关键词映射到数组的某个位置,直接访问该位置获取对应值(如文档列表)。 - 优势 :
理想情况下查询时间复杂度为 O (1),适合高频、精确的键值对查询。 - 局限 :
不支持范围查询或前缀匹配,且哈希冲突需要额外处理(如链地址法)。
图结构(Graph)
- 用途 :用于关联检索(如知识图谱中的实体关系查询)和网页链接分析(如 PageRank 算法)。
- 原理 :
以节点表示实体(如网页、人物、概念),边表示关系(如 "网页 A 链接到网页 B""张三是李四的朋友")。 - 优势 :
能高效表达复杂的关联关系,支持多跳查询(如 "北京→中国→亚洲" 的地理关系链)。
布隆过滤器(Bloom Filter)
- 用途 :用于快速判断 "某个关键词是否不存在",减少无效查询(如过滤掉不可能包含关键词的文档)。
- 原理 :
通过多个哈希函数将关键词映射到一个二进制数组,若数组中对应位置全为 1,则 "可能存在";若有 0,则 "一定不存在"(存在一定误判率,但可通过参数调整)。 - 优势 :
空间效率极高,时间复杂度 O (k)(k 为哈希函数数量),适合在查询初期快速过滤无关文档,降低后续处理压力。
总结
搜索引擎是多种数据结构的 "组合体":
- 倒排索引负责核心的关键词 - 文档映射;
- 字典树 和布隆过滤器优化查询效率和体验;
- B 树 / B + 树 和哈希表支撑底层存储和快速访问;
- 图结构处理复杂关联关系