前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何设计一个搜索引擎

如何设计一个搜索引擎

作者头像
IT可乐
发布于 2022-05-09 06:10:21
发布于 2022-05-09 06:10:21
2.6K0
举报
文章被收录于专栏:IT可乐IT可乐

1、什么是检索?

指从用户特定的信息需求出发,对特定的信息集合采用一定的方法、技术手段,根据一定的线索与规则从中找出相关信息

对应到我们实际工作中,检索其实就是:

如何用最小的内存(物理成本),最快(时间成本)的取出我们需要的数据。

2、检索体系架构

3、存储介质层

3.1 磁盘为什么能存储数据

机械硬盘的磁盘主体是一块金属薄片(也有用其他材料的),上面涂覆一层磁性材料,可以理解为一层小磁针。

硬盘工作时,磁盘在马达的驱动下高速旋转,转速高达数千转每分钟,磁头则在磁头驱动系统的的控制下,在高速旋转的磁盘表面飞行。

①、写数据

磁头线圈上通电,在其周围产生磁场,磁化磁盘表面的磁性材料,不同方向的电流产生的磁场方向不同,磁盘表面的磁性材料被磁化的极性也不同,不同极性便代表0与1;

②、读数据

磁头线圈切割磁盘表面的磁性材料的磁场,产生电信号,不同极性的磁性材料产生的感应电流方向不同,因此可以读出0与1。

注意:断电并不会影响磁盘表面的磁性材料的极性,因此断电后数据仍然不会消失,但剧烈的碰撞或加热则有可能导致数据丢失

3.2 磁盘和内存的区别

①、持久性

磁盘能永久存储(HDD10年,SDD5年),断电不丢失数据;

内存断电即丢失数据。

②、容量

磁盘通常是几百G到几个T;

内存通常是几个G到几十个G。

③、价格

内存 > 磁盘

④、读写速度

内存 > SDD > HDD

4、数据结构层

4.1 数组

1.数组是相同数据类型的元素的集合。 2.数组各元素是按照先后顺序连续存储的。 3.插入慢:无序数组末尾插入快,其余情况需要维护数组地址连续效率都是比较差。 4.查找:支持下标随机查找快,有序数组也可以用诸如二分法加快查找速度。 5.删除慢:和插入类似,除了末尾插入快。其余情况需要维护数组地址连续都比较慢。

4.2 链表

1.链表物理存储单元上非连续(可以充分利用计算机内存)、非顺序的存储结构。 2.不支持随机读取。 3.存储空间会增大,比如单向链表每个节点都会存储下一个节点的引用。 4.插入快。 5.删除快。 6.查找慢。

其余比如栈、队列、二叉树,红黑树,B+树等等都是这两种数据结构的单独变化或组合变化。

4.3 栈

栈只支持两个基本操作:入栈 push()和出栈 pop()。

典型应用:

①、实现字符串逆序;

②、判断标签是否匹配;

③、计算机中的函数调用;

4.4 队列

和栈类似,也只支持两个操作:入队 enqueue(),放一个数据到队列尾部;出队 dequeue(),从队列头部取一个元素。

①、单向队列(Queue):只能在一端插入数据,另一端删除数据。

②、双向队列(Deque):每一端都可以进行插入数据和删除数据操作。

③、优先级队列(Priority Queue):数据项按照关键字进行排序,关键字最小(或者最大)的数据项往往在队列的最前面,而数据项在插入的时候都会插入到合适的位置以确保队列的有序。

④、阻塞队列(Block Queue):在队列为空的时候,从队头取数据会被阻塞。因为此时还没有数据可取,直到队列中有了数据才能返回;如果队列已经满了,那么插入数据的操作就会被阻塞,直到队列中有空闲位置后再插入数据,然后再返回。

典型的生产者-消费者模型。

⑤、并发队列

典型应用:

①、线程池

②、数据库连接池

对于大部分资源有限的场景,当没有空闲资源时,基本上都可以通过“队列”这种数据结构来实现请求排队。

4.5 树

链表的插入和删除比较快,但是查找却比较慢,因为不管我们查找什么数据,都需要从链表的第一个数据项开始,遍历到找到所需数据项为止,这个查找也是平均需要比较N/2次。

那么有没有一种数据结构能同时具备数组查找快的优点以及链表插入和删除快的优点,于是 树 诞生了。

①、二叉树

二叉树的相关介绍:https://cloud.tencent.com/developer/article/1013261

二叉树的每个节点最多只能有两个子节点,如下图:

如果左节点比根节点小,右节点比根节点大,那就是平衡二叉树。二叉搜索树的效率在O(N)和O(logN)之间,取决于树的不平衡程度。最差也会退化成一个链表。

②、红黑树

为了避免二叉树退化成链表,需要尽量保证树的平衡,于是有了 红黑树。

红黑树的相关介绍:https://cloud.tencent.com/developer/article/1079403

③、B+树

上面说的树每个节点都最多只能有两个子节点,有些情况下,数据量特别大,会导致树的高度很大,这会导致我们查找某个数据需要多次IO,要知道 IO 相对而言是很慢的,有没有可能每个节点能有很多字节点呢?

类似 B+ 树,2-3-4 树诞生了。

典型应用:关系型数据库存储数据结构。

1.数据很大,不可能全部存储在内存中,还要持久化,故要存储到磁盘上。

2.减少查找过程中磁盘I/O的存取次数。

局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。

与磁盘预读,预读的长度一般为页(page)的整倍数,(在许多操作系统中,页得大小通常为4k)

叶子节点数据多。

3.支持范围查找

④、LSM 树

Log Structured Merge Trees

一个日志系统有如下特征:

一、数据量大且持续生成

二、写入操作会特别频繁

三、查询快,且查询一般不是全范围的随机搜索,而是近期检索。

B+ 树为什么不行?(叶子节点存储在磁盘中,需要随机写磁盘,数据量大会导致性能急剧下降)

LSM 树:

内存树存放近期写入的数据,有序且支持更新,支持随时查询。磁盘树则通常有多个,顺序写入。

⑤、Trie 树

字典树、前缀树、单词查找树。

典型应用:

字符串检索

百度谷歌搜索框

拼写检查

4.6 跳表

链表的基础上增加了多级索引。

Redis 中的有序集合(Sorted Set)就是用跳表来实现的。

4.7 散列表

散列表相关介绍:https://cloud.tencent.com/developer/article/1079392

通过把关键值映射到表中一个位置来访问记录,这个映射函数叫做散列函数,存放记录的数组叫做散列表。

解决哈希冲突:

①、开放寻址法:线性探测、双重散列

②、链表法

散列表设计原则:

①、散列函数

②、初始容量;

③、装载因子;

④、散列冲突解决办法;

典型应用:

①、有限的数据集合中快速查询数据

比如:Word 文档中单词拼写检查功能是如何实现的?

常用的英文单词有 20 万个左右,假设单词的平均长度是 10 个字母,平均一个单词占用 10 个字节的内存空间,那 20 万英文单词大约占 2MB 的存储空间,就算放大 10 倍也就是 20MB。

所以可以将全部英文单词放到散列表,用户输入单词直接去散列表里面查,没有就报错。

②、词频统计、访问统计等等。

4.8 布隆过滤器

布隆过滤器相关介绍:https://cloud.tencent.com/developer/article/1638225

简单来说就是一个二进制数组。

典型应用:数据海量,不要求一定准确的场景。

①、判断ID是否已经注册,即使误判也能容忍。

②、爬虫判断网页是否已经爬过。

4.9 图

存储:

①、邻接矩阵

②、邻接表

DFS(Deep First Search)深度优先搜索算法

BFS(Breath First Search)广度优先搜索算法

飞机航线

电子线路

城市地图

好友关系

5、算法层

比较好用的查找算法是二分法O(logn),在有序的数据结构中是特别bug的,但是如何进行快速的排序,有如下常用的排序算法:

实际应用:

①、如何根据年龄给100W用户排序?

利用桶排序,从1岁到150岁(有人会说超过150岁,这里超过三界之外的人不算),建立150个桶,然后遍历这100W个用户,依次放入150个桶中,遍历完,边排好序了。

②、如何快速查询每个考生的高考排名?

同样也是桶排序,高考分数0-750,也就是顶多 750 个桶。

6、业务设计层

6.1 爬虫系统

通过高性能的爬虫系统来完成网页的持续抓取,然后将抓取到的网页存入存储平台中。

一般来说是是将抓取到的网页存放在基于 LSM 的 HBase 中,以便支持数据的高效读写。

①、爬取网页

首先找到权重较高的网页,比如新浪、腾讯,通过广度优先搜索算法放入爬取队列中;

计算网页权重算法:PageRank

网页太多,持久化队列,便于断点爬取。

如何爬取网页链接:可以获取到网页的 HTML 文件,看成一个大的字符串,然后利用字符串匹配算法,获取 或者 这样的标签内容。

②、网页去重

利用布隆过滤器。

需要注意的是:布隆过滤器是在内存中的,如果机器重启,布隆过滤器就会被清空,防止网页重复爬取,需要持久化布隆过滤器,比如定时每半小时持久化一次。

③、原始网页存储

便于后面的离线分析,索引构建,需要将海量的原始网页存储。

网页很多,通常的文件系统不适合存储这么多的文件,而是将多个网页存储在一个文件中。

④、网页编号和链接存储

上一步给每个网页分配了一个id,在存储网页的同时,也将网页编号和网页链接存储在一个文件中。

6.2 分析索引系统

①、抽取网页文本信息

网页都是遵循 HTML 规范的,只需要去掉JavaScript代码、CSS代码,还有比如下拉框的代码。

在网页这个大字符串中,一次性查找 , , </option)为止。而这期间遍历到的字符串连带着标签就应该从网页中删除。

②、网页质量分析

去掉低质量的垃圾网页

③、反作弊

避免一些作弊网页来干扰搜索结果

④、分词创建临时索引

抽取到网页文本信息之后,对文本信息进行分词,并创建临时索引文件。

英文网页:只需要通过空格、标点符号等分隔符,将每个单词分割开来就可以了。

中文网页:借助词库并采用最长匹配规则,来对文本进行分词。

临时索引文件如下:

注意这里存的是单词编号,因为单词很多,为了节省内存,用一个散列表存储:单词编号-单词。

⑤、通过临时索引创建倒排索引

⑥、记录单词编号在倒排索引文件的偏移位置

帮助我们快速地查找某个单词编号在倒排索引中存储的位置,进而快速地从倒排索引中读取单词编号对应的网页编号列表。

6.3 查询

doc_id.bin:记录网页链接和编号之间的对应关系。

term_id.bin:记录单词和编号之间的对应关系。

index.bin:倒排索引文件,记录每个单词编号以及对应包含它的网页编号列表。

term_offsert.bin:记录每个单词编号在倒排索引文件中的偏移位置。

①、当用户在搜索框中,输入某个查询文本的时候,我们先对用户输入的文本进行分词处理。假设分词之后,我们得到 k 个单词。

然后对这 k 个单词进行纠错模型判断:

②、纠错完成之后,我们拿这 k 个单词,去 term_id.bin 对应的散列表中,查找对应的单词编号。经过这个查询之后,我们得到了这 k 个单词对应的单词编号。

③、我们拿这 k 个单词编号,去 term_offset.bin 对应的散列表中,查找每个单词编号在倒排索引文件中的偏移位置。经过这个查询之后,我们得到了 k 个偏移位置。

④、我们拿这 k 个偏移位置,去倒排索引(index.bin)中,查找 k 个单词对应的包含它的网页编号列表。经过这一步查询之后,我们得到了 k 个网页编号列表。

⑤、我们针对这 k 个网页编号列表,统计每个网页编号出现的次数。具体到实现层面,我们可以借助散列表来进行统计。统计得到的结果,我们按照出现次数的多少,从小到大排序。出现次数越多,说明包含越多的用户查询单词(用户输入的搜索文本,经过分词之后的单词)。

经过这一系列查询,我们就得到了一组排好序的网页编号。我们拿着网页编号,去 doc_id.bin 文件中查找对应的网页链接,分页显示给用户就可以了。

10、总结

检索核心思路:通过合理的组织数据,尽可能的快速减少查询范围。

①、合理选择存储介质、存储数据结构;

②、合理创建索引,使得索引和数据分离;

③、减少磁盘IO,将频繁读取的数据加载到内存中;

④、读写分离;

⑤、分层处理;

参考文档:极客时间《数据结构与算法之美》

数组:https://cloud.tencent.com/developer/article/1013247

链表:https://cloud.tencent.com/developer/article/1013272

栈:https://cloud.tencent.com/developer/article/1013249

队列:https://cloud.tencent.com/developer/article/1013262

二叉树:https://cloud.tencent.com/developer/article/1013261

红黑树:https://cloud.tencent.com/developer/article/1079403

2-3-4树:https://cloud.tencent.com/developer/article/1079396

哈希表:https://cloud.tencent.com/developer/article/1079392

图:https://cloud.tencent.com/developer/article/1079391

布隆过滤器:https://cloud.tencent.com/developer/article/1638225

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
React Native备课笔记Day01一、React Native介绍二、特点分析三、推荐网站以及运行第一个react native项目四、环境搭建五、React Native文件结构六、View
(本节包括React Native介绍、特点分析、环境搭建、RN文件结构、View组件讲解、FlexBox布局及props与state) 一、React Native介绍 RN是React native的简称。在2015年的3月26日,Facebook公司正式发布了这一套框架,使用React框架跨平台开发原生移动应用的开源技术框架。有了跨平台这个特性,开发者可以使用React native高效的在Android和iOS开发应用程序。毕竟人家的标语就叫做Learn once,write anywhere。re
谦谦君子修罗刀
2018/05/02
4K0
React Native备课笔记Day01一、React Native介绍二、特点分析三、推荐网站以及运行第一个react native项目四、环境搭建五、React Native文件结构六、View
ReactJs和React Native的那些事
介绍  1,React Js的目的 是为了使前端的V层更具组件化,能更好的复用,它能够使用简单的html标签创建更多的自定义组件标签,内部绑定事件,同时可以让你从操作dom中解脱出来,只需要操作数据就会改变相应的dom。  2,React Native的目的 是希望我们能够使用前端的技术栈就可以创建出能够在不同平台运行的一个框架。可以创建出在移动端运行的app,但是性能可能比原声app差一点。  3,ReactJs和React Native的原理是相同的,都是由js实现的虚拟dom来驱动界面view层渲染。
xiangzhihong
2018/02/05
2.2K0
ReactJs和React Native的那些事
react-native 开发笔记(一)
一般app的设计都是主页是一个tab页面,我们的app产品也是不例外的,所以我使用了这个iOS专用的组件(先搞定ios,再考虑兼容性)
frontoldman
2019/09/02
6050
React-Native入门指南(一)
最近手头的工作繁多,有研究性的项目和系统研发,正好遇到同事离职,接手了框架的UI组件,不仅需要维护和填坑,还需要开发新的功能组件。因为身在H5-Hybird的框架部门,最近团队开始尝试使用React-Native来做些东西。之前也有过开发iOS App的冲动,学了点Object-c,这次正好借此机会进入App开发,以弥补自己在Native-App上的经验不足。
疯狂的技术宅
2019/03/28
2.4K0
React-Native入门指南(一)
React Native之Navigator
移动应用很少只包含一个页面。从你添加第二个页面开始,就得考虑如何管理多个页面间的跳转了。 导航器正是为此而生。它可以管理多个页面间的跳转,也包含了一些常见的过渡动画,包括水平翻页、垂直弹出等等。 Na
xiangzhihong
2018/02/05
1.6K0
React Native之Navigator
React Native入门遇到的一些问题
curl -LsSf http://github.com/mxcl/homebrew/tarball/master | sudo tar xvz -C/usr/local --strip 1
meteoric
2018/11/20
1K0
四、HarmonyOS应用开发-ArkTS开发语言介绍
TypeScript 是一个开源的编程语言,本章节只介绍了TypeScript的基础语法知识,更多内容大家可以参考 TypeScript 的官方教程(https://www.typescriptlang.org/docs/)。大家在学习过程中,如果没有搭建TypeScript的开发环境,也可以直接使用在线 Playground 平台(https://www.typescriptlang.org/play)进行编码练习。没有接触过 TypeScript 的同学可以先补齐相关的语法基础,再进入 HarmonyOS 的相关开发学习之旅。
跟着飞哥学编程
2024/05/24
8600
四、HarmonyOS应用开发-ArkTS开发语言介绍
React Native之React速学教程(下)
React Native之React速学教程(下) 本文出自《React Native学习笔记》系列文章。 React Native是基于React的,在开发React Native过程中少不了的需要用到React方面的知识。虽然官方也有相应的Document,但篇幅比较多,学起来比较枯燥。 通过《React Native之React速学教程》你可以对React有更系统和更深入的认识。为了方便大家学习,我将《React Native之React速学教程》分为上、中、下三篇,大家可以根据需要进行阅读学习。 概
CrazyCodeBoy
2018/05/07
2.9K0
会写 TypeScript 但你真的会 TS 编译配置吗?
随着 TypeScript 的流行,越来越多的项目通过使用 TypeScript 来实现编写代码时候的类型提示和约束,从开发过程中减少 BUG 出现的概率,以此提升程序的健壮性和团队的研发效率。
小东同学
2022/07/29
4.2K1
会写 TypeScript 但你真的会 TS 编译配置吗?
react-native总结心得
一、prop,state,ref 1.ref:引用一个组件(是从render中返回该组件实例) 2.props:组件中的属性, 2.1常用于跳转页面的传值:this.props.navigator.push({component:xxx,id:this.props.id}) 2.2不同组件之间传值 2.3子组件向父组件传值 3.state:组件中的状态 父组件向子组件传值 二、react-native组件思想 react-native的组件其实是采用的react的组件思想,
IT架构圈
2018/05/31
1.4K0
TS+React+Router+Mobx+Koa打造全栈应用
效果图 Todo.gif Typescript 在TS下开发首先要做好相应的环境配置,一些需要进行设置的编译选项 # tsconfig.json { "compilerOptions":{
MrTreasure
2018/05/10
1.9K0
React Native 从诞生到现在
感谢支持ayqy个人订阅号,每周义务推送1篇(only unique one)原创精品博文,话题包括但不限于前端、Node、Android、数学(WebGL)、语文(课外书读后感)、英语(文档翻译) 如果觉得弱水三千,一瓢太少,可以去 http://blog.ayqy.net 看个痛快
ayqy贾杰
2019/12/02
1.3K0
React Native 从诞生到现在
ReactJS到React-Native,架构原理概述
React是一个纯JS的UI库,只能干HTML/CSS/JS 提供的Web服务(新的H5 API不一定支持), React-Native厉害在于它能打通JS和Native Code, 让JS能够调用丰富的原生接口,充分发挥硬件的能力, 实现非常复杂的效果,同时能保证效率和跨平台性。
周陆军博客
2023/04/09
5.7K0
React-Native开发规范文档
方式表达逻辑,【强制】请勿超过3层, 超过请使用状态设计模式。 正例:逻辑上超过 3 层的 if-else 代码可以使用卫语句,或者状态模式来实现。
conanma
2021/11/02
2.2K0
「译」面向 JavaScript 开发人员的 TSConfig 简介
JavaScript 从最初作为一种简单的脚本语言开始不断发展,成为用于构建复杂应用程序的强大、现代的语言工具。为了管理更大、复杂的代码库,JavaScript 开发人员不断寻找方法改善他们的工作流程、代码质量和生产力。TypeScript 是一个通过添加类型来提高代码质量和维护效率的重大创新,因此毫不奇怪它是目前增长最快的语言之一。
泯泷、
2024/07/21
2360
React Native 新架构
本文主要介绍FB团队正在重构的ReactNative(下面称RN)新架构,主要当前架构,Bridge带来的问题,新架构,JSI,Fabric,TurboModules,CodenGen及LeanCore等概念。
zz_jesse
2020/11/24
1.8K0
React Native 新架构
【Hybrid开发高级系列】ReactNative(三)——RN能力简介
http://facebook.github.io/react-native/docs/getting-started.html
江中散人_Jun
2023/10/16
4480
【Hybrid开发高级系列】ReactNative(三)——RN能力简介
使用rollup打包React Native插件并发布
我们写组件库或工具库时不可避免会用到外部库,这些外部库可能是符合 CommonJS 规范的。而 Rollup 力图实现 ES 模块的规范, 因此,加载 CommonJS 模块和使用 Node 模块位置解析逻辑都被实现为可选插件,默认情况下不在 Rollup 内核中。我们需要安装并配置 CommonJS 和 node-resolve 插件。
用户1250838
2021/05/31
2.4K0
React-Native入门指南 终章
在facebook React-native的官网可以看到目前支持的组件如下: https://facebook.github.io/react-native/docs/getting-started.html#content
疯狂的技术宅
2019/03/28
1.6K0
React-Native入门指南 终章
React Native之react-native-scrollable-tab-view详解
在React Native开发中,官方为我们提供的Tab控制器有两种:TabBarIOS和ViewPagerAndroid。TabBarIOS,仅适用于IOS平台 ViewPagerAndroid,仅适用于Android平台(严格来讲并不算,因为我们还需要自己实现Tab)。在项目开发中,我们优先选择一些开源兼容性比较好的第三方库,例如,react-navigation,以及本文即将说到的react-native-scrollable-tab-view(官方地址)。react-native-scrolla
xiangzhihong
2018/02/06
6.7K0
React Native之react-native-scrollable-tab-view详解
相关推荐
React Native备课笔记Day01一、React Native介绍二、特点分析三、推荐网站以及运行第一个react native项目四、环境搭建五、React Native文件结构六、View
更多 >
LV.2
中国平安架构师
目录
  • 1、什么是检索?
  • 2、检索体系架构
  • 3、存储介质层
    • 3.1 磁盘为什么能存储数据
    • 3.2 磁盘和内存的区别
  • 4、数据结构层
    • 4.1 数组
    • 4.2 链表
    • 4.3 栈
    • 4.4 队列
    • 4.5 树
    • 4.6 跳表
    • 4.7 散列表
    • 4.8 布隆过滤器
    • 4.9 图
  • 5、算法层
  • 6、业务设计层
    • 6.1 爬虫系统
    • 6.2 分析索引系统
    • 6.3 查询
  • 10、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档