资讯动态

【DIY系列:自己动手写分布式搜索引擎】第02篇:搜索引擎的五脏六腑:核心模块全景图

发布时间:2026/10/18 6:49:33 来源:尧图企业网站定制
上一篇【第01篇】为什么要自己造轮子搜索引擎工程师的自我修养下一篇【第03篇】从敲下关键词到看到结果一次搜索的完整旅程摘要很多人以为搜索引擎就是输入关键词返回结果。真这么简单这行也没那么多人头疼了。一个能用的搜索引擎肚子里至少装着三大核心和三个辅助模块。本文给你画一张全身像把采集、索引、检索这三块硬骨头连同容易被忽视的用户界面、分布式计算、文本挖掘一起拆开看顺便说清单机和分布式到底差在哪。一、先给搜索引擎画个全身像抛开具体技术搜索引擎干的事其实就一句把一堆文档变成能按关键词快速找到文档的东西。为了干成这件事它分成了几层。【搜索引擎总体架构】 ┌──────────────────────────────────────────┐ │ 用户界面 (搜索框/结果页) │ └───────────────────┬──────────────────────┘ │ 查询请求 ▼ ┌──────────────────────────────────────────┐ │ 检索层 (查询/打分/排序) │ └───────────────────┬──────────────────────┘ │ 读取索引 ▼ ┌──────────────────────────────────────────┐ │ 索引层 (倒排/正排/DocValues) │ └───────────────────┬──────────────────────┘ │ 消费文档 ▼ ┌──────────────────────────────────────────┐ │ 采集层 (网络爬虫/数据导入) │ └──────────────────────────────────────────┘ 辅助模块横切分布式计算(横向扩展) / 文本挖掘(语义) / 监控运维从上往下看数据流的箭头是反的文档先被采集再被建索引查询时检索层读索引返回结果最后在界面上展示。这跟我们写业务系统的请求-响应顺序正好相反很多新人一开始转不过这个弯。二、采集层爬虫在忙什么没有文档后面全是空谈。采集层的活儿是把分散在各处的原始内容聚拢过来。最典型的就是网络爬虫。它从一批种子 URL 出发把网页抓下来解析出里面的链接继续抓像个停不下来的采风人。爬虫要操心的事不少礼貌抓取别把人家服务器压垮、去重同一篇文章别抓八百遍、增量更新只抓变了的内容。但工程里的采集层未必是爬虫。你给自己的商品库建搜索数据源就是数据库写个定时任务把数据读出来就行。所以更准确的说法是数据导入爬虫只是其中一种。后面我们会专门花一篇聊爬虫这里先留个印象。三、索引层把文档变成能查的结构这是搜索引擎真正的心脏也是后面我们亲手写代码的主战场。它的核心产物叫倒排索引不再按文档找词而是按词找文档。举个生活里的例子。一本书后面有关键词索引你查倒排这个词索引告诉你它在第 12、45、78 页。搜索引擎干的正是这件事只不过书有几百页网页有几十亿条。【正排 vs 倒排】 正排文档 → 内容 倒排词 → 文档列表 ┌──────────────┐ ┌──────────────────────┐ │ 文档1: 我爱搜索 │ │ 搜索 → [文档1, 文档3] │ │ 文档2: 天气真好 │ │ 天气 → [文档2] │ │ 文档3: 搜索很有趣│ │ 有趣 → [文档3] │ └──────────────┘ └──────────────────────┘ 查搜索得翻遍所有文档 查搜索直接拿到文档列表倒排索引为什么快因为查询时不用遍历全部文档直接拿词去倒排表里取。这个朴素的思想撑起了整个搜索行业。后面第二段我们会从零写一个倒排索引你会明白它远不止词→列表这么简单。四、检索层用户查询怎么变成结果索引建好检索层负责接住用户的查询返回相关结果并排好序。一次查询通常要走过这几步把用户输入分词拿每个词去倒排里取文档列表多个词做交集或并集这就是布尔查询再给每个文档算一个相关性分数最后按分数排序返回前 N 条。打分这件事看着简单其实有大学问。TF-IDF、BM25 这些名字你大概听过它们的核心都在回答一个问题凭什么这条结果排第一、那条排第十这部分在 Lucene 原理篇会重点拆解这里先记住检索层 取倒排 合并 打分排序这个骨架。五、三个容易被忽视的辅助模块前面三大件是主干但一个能上线的搜索引擎还离不开三个辅助角色。用户界面。搜索框、结果页、筛选侧栏、翻页这些决定了用户用得爽不爽。内核再强界面拉胯也白搭。分布式计算。文档量小的时候一台机器就扛住了。可当你有百亿级网页、或者每秒几万次查询单机根本装不下也扛不住。这时候得把索引拆到多台机器上查询时合并结果。分布式是后面 SolrCloud 和 ES 的重头戏。文本挖掘。纯关键词匹配有天花板。用户搜怎么减肥你库里只有减重方法字面不匹配就搜不到。同义词、语义理解这些就属于文本挖掘能让搜索引擎更懂人话。【单机 vs 分布式差在哪】 单机搜索引擎 分布式搜索引擎 ─────────── ─────────────── 一份完整索引在本地 索引切成多片分散在多节点 查询自己搞定 查询发给各分片再汇总 挂了就全挂 副本兜底挂一个还能跑 扩容量 换更大的机器 扩容 加机器六、单机 vs 分布式差在哪上面这张对比表值得多盯两秒。单机搜索引擎我们第二段就会写出来它简单、好调试但天花板明显索引大小受单机磁盘限制查询压力受单机 CPU 限制。分布式搜索引擎把索引切成多个分片shard每个分片可以有多份副本replica。一次查询被广播到相关分片各自算完再把结果汇总排序。某台机器挂了副本顶上服务不中断。代价是引入了一堆新问题分片怎么切、请求怎么路由、集群状态怎么保持一致。这些恰恰是 Solr 和 Elasticsearch 存在的理由。七、把模块拼回一条线一个查询的跨部门之旅光看模块清单还是有点抽象拿一个具体查询串一遍。假设用户在界面输入无线耳机 便宜回车。第一步用户界面把这句话交给检索层顺手记一笔搜索日志后面分析查询意图要用。第二步检索层先分词得到无线“耳机”便宜三个词分别去索引层取倒排表做交集得到候选文档再给每个文档打分排序取前十条。第三步检索层发现结果里要展示标题和价格于是去索引层的正排里把这几篇文档的详情取出来。第四步返回用户界面渲染成结果页。整个过程里采集层没参与因为它早就在离线阶段把文档送进索引了此刻在睡觉。【一次查询的跨部门流转】 界面: 无线耳机 便宜 │ 分词 ▼ 检索层: 查倒排→求交→打分排序→取Top10 │ 取详情 ▼ 索引层: 倒排(找) 正排(取详情) │ ▼ 界面: 渲染结果页 采集层离线阶段已完工此刻休眠这一圈走下来你应该体会到模块之间是怎么咬合的。再补一张职责表方便你后面动手时对着填空模块它负责它不负责采集层把原始内容搬进来、清洗怎么建索引索引层倒排 正排存与取用户交互检索层分词后查、合并、打分数据从哪来用户界面输入框、结果页、筛选内部算法分布式计算横向扩、容错单条查询逻辑文本挖掘同义词、语义基础匹配把这张表贴在显示器边上写代码时就不会把逻辑塞错地方。模块边界清晰是后面我们能一层层往下写的前提。八、模块之间怎么通信接口而非实现第七节的职责表把边界画得很清楚落到代码上关键是用接口衔接模块而不是互相硬编码。举个后面的例子分词模块 Analyzer 就该定义成一个接口输入文本、输出词项流至于背后是空格切分还是智能中文分词索引层和检索层根本不关心。哪天你想换更好的分词器只换实现不动主干。【用接口解耦模块】 检索层 ──▶ Analyzer接口 ──▶ 空格分词 / 中文分词(可替换) 检索层 ──▶ IndexReader接口 ──▶ 内存索引 / 磁盘索引(可替换)这种面向接口的写法在后面手写引擎时我会反复强调。它带来的好处立竿见影单元测试时你能用最简单的空格分词替身把检索逻辑测干净不被分词细节干扰上线时再换生产级分词器。搜索引擎之所以难写一半难在算法另一半难在怎么把一堆零件拼得不拧巴而接口就是让零件不拧巴的润滑剂。最后提醒一句新手最容易犯的错就是把分词逻辑直接写进索引代码里结果想换分词器时牵一发动全身。从一开始就把模块间的契约接口定清楚后面省下的返工时间够你多写两个功能。本篇小结搜索引擎的五脏六腑归纳起来是采集层、索引层、检索层三大核心外加用户界面、分布式计算、文本挖掘三个辅助模块。索引层里的倒排索引是整个系统的心脏检索层靠取倒排 合并 打分产出结果。单机版简单清晰分布式版能横向扩展但引入了协调与容错的复杂度。下一篇我们跟着一次真实的搜索把这些模块串起来走一遍看看从你敲下关键词到看到结果中间到底发生了什么。上一篇【第01篇】为什么要自己造轮子搜索引擎工程师的自我修养下一篇【第03篇】从敲下关键词到看到结果一次搜索的完整旅程

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑