您当前的位置:首页 > 电脑百科 > 站长技术 > 搜索引擎

开发者手撸类谷歌搜索关键字智能匹配功能系统

时间:2020-08-10 10:21:55  来源:  作者:

如果你用谷歌或者百度进行搜索就会发现,当你在这些搜索引擎的框内键入某些内容时,它们可以根据输入的内容智能展现输入提示建议。本文作者正是带着这样的想法实现了一个具备类似功能的系统。

本文将展现如何设计一个大规模的自动完成输入提示建议的系统,就像 google 搜索一样,整个设计是用 Docker Compose 实现的,可以在这里找到源代码:https://github.com/lopespm/autocomplete

开发者手撸类谷歌搜索关键字智能匹配功能系统

 

系统要求

最终的系统需要适应类似 Google 的搜索规模,即每天约 50 亿次搜索,也就是每秒钟约 5.8 万次查询。我们可以预期这些搜索中有 20% ,也就是每天有 10 亿次查询。

如果我们选择为这 10 亿条查询建立索引的话,平均每个查询有 15 个字符【2】,每个字符有 2 个字节(我们将只支持英语设置),这反映在托管这些查询所需的存储空间大约为 30 GB。

功能要求

  • 根据用户输入(前缀)获取热门的短语建议列表。
  • 通过加权按给定短语 / 查询的频率和相似度对建议进行排序【3】。

主要的两个 API 是:

  • top-phrases(prefix) :返回给定前缀的热门短语列表。
  • collect-phrase(phrase) :将搜索到的短语提交给系统。稍后,汇编器将使用这个短语来构建数据结构,这个数据结构将前缀映射到热门短语列表。

非功能性需求

  • 高可用;
  • 性能:热门短语的响应时间应快于用户的输入速度(<200ms);
  • 可扩展性 :系统应该能够适应大量请求,同时保持性能;
  • 持久性 :即使存在硬件故障或发生系统崩溃,先前搜索的短语(对于给定的时间跨度)也应该可用。

设计与实现

高级设计

开发者手撸类谷歌搜索关键字智能匹配功能系统

 

两个主要的子系统是:

  • 分发服务器:负责处理用户对给定前缀的热门短语的请求。
  • 汇编器:负责收集用户搜索并将它们汇编成数据结构,稍后由分发服务器使用。

详细设计

开发者手撸类谷歌搜索关键字智能匹配功能系统

 

这个实现使用了现成的组件,如 Kafka(消息代理)、Hadoop(MapReduce 和分布式文件系统)、redis(分布式缓存)和 Nginx(负载平衡、网关、反向代理)等,但是也有用 Python 构建的定制服务,即 Trie 分发和构建服务,Trie 数据结构也是定制的。

这个实现中的后端服务被构建为可持续使用,不需要太多编排。例如,如果一个活动后端主机停止响应,则它对应的临时节点 znode 注册表最终会消失,而另一个备用后端节点将尝试通过 zookeeper 上的 临时节点 znode 声明该位置来取代它的位置。

Trie:基础数据结构

分发服务器使用并提供给分发服务器的数据结构是 Trie ( 译注 :又称前缀树、字典树,是一种有序树,用于保存关联数据),其每个前缀节点都有一个热门短语列表。热门短语是使用 享元模式(flyweight pattern)进行引用的,这意味着短语的字符串文字仅存储一次。每个前缀节点都有一个热门短语列表,这是对字符串文本的引用列表。

正如我们之前看到的,我们将需要大约 30 GB 来索引 10 亿个查询,这大约是上述 Trie 存储 10 亿个查询所需的内存。由于我们希望将 Trie 保存在内存中,以便为给定的查询启用快速查找时间,因此,我们将 Trie 划分为多个 Trie,每个 Trie 在不同的机器上进行。这一做法减轻了任何给定机器上的内存负载。

为了提高可用性,托管这些 Trie 的服务也将具有多个副本。为了提高持久性,Trie 的序列化版本将在分布式文件系统(HDFS)中可用,并且可以通过 MapReduce 作业以一种可预测的、确定性的方式重新构建。

信息流

汇编器:收集数据并汇编 Trie

1、客户端通过 http://localhost:80/search?phrase="a user query" 将搜索到的短语提交到网关:

2、由于搜索服务器不在此实现的范围内,网关通过 http://assembler.collector-load-balancer:6000/collect-phrase?phrase="a user query" 直接将搜索短语发送到收集器的负载均衡器:

3、收集器的负载均衡器通过 http://assembler.collector:7000/collect-phrase?phrase="a user query" 将请求转发到其中一个收集器后端:

4、收集器后端向消息代理(Kafka)发送短语主题的消息。关键和价值在于短语本身【4】。

5、Kafka Connect HDFS Connector 汇编器。kafka-connect 将短语主题中的消息转储到 /phrases/1_sink/phrases/{30 minute window timestamp} 【5】文件夹【6】中。

6、 触发 MapReduce 作业【7】:通过加权每个短语的新近度和频率,它们将搜索的短语减少到一个单独的 HDFS 文件中【8】。

  • 根据当前时间生成一个 TARGET_ID ,例如: TARGET_ID=20200807_1517 。
  • 第一个 MapReduce 作业针对 K【9】 最近的 /phrases/1_sink/phrases/{30 minute window timestamp 文件夹执行,并为这些文件夹中的每一个赋予一个基本权重(越近,则基本权重越高)。这个作业还将计算给定文件夹中相同短语的权重。生成的文件将存储在 /phrases/2_with_weight/2_with_weight/{TARGET_ID} 文件夹中。
  • 第二个 MapReduce 作业将把给定短语的所有权重从 /phrases/2_with_weight/2_with_weight/{TARGET_ID} 汇总到 /phrases/3_with_weight_merged/{TARGET_ID} 。
  • 第三个 MapReduce 作业将通过递减权重对条目进行排序,并将它们通过单个 Reducer,以生成单个文件。此文件放在中 /phrases/4_with_weight_ordered/{TARGET_ID} 。
  • zookeper znode /phrases/assembler/last_built_target 被设置为 TARGET_ID 。

7、Trie Builder 服务正在监听 / phrases/assembler/last_built_target zonde 中的更改,它基于 /phrases/4_with_weight_ordered/{TARGET_ID} 文件为每个分区【10】构建 Trie。例如,一个 Trie 可以覆盖前缀直到 mod,另一个从 mod 到 racke,还有一个从 racke 开始。

  • 每个 Trie 被序列化并写入 /phrases/5_tries/{TARGET_ID}/{PARTITION} HDFS 文件(例如, /phrases/5_tries/20200807_1517/mod|racke ),而 zookeeper znode /phrases/distributor/{TARGET_ID}/partitions/{PARTITION}/trie_data_hdfs_path 被设置为前面提到的 HDFS 文件路径。
  • 该服务将 zookeper znode /phrases/distributor/next_target 设置为 TARGET_ID 。

将 Trie 转移到分发服务器子系统

1、分发服务器后端可以处于活动模式(服务请求)或备用模式。处于备用模式的节点将获取最近的 Trie,将它们加载到内存中,并将自己标记为准备接管活动位置。具体如下:

a. 备用节点在监听对 znode /phrases/distributor/next_target 的更改时,检测其修改并为每个每个分区创建一个 临时的顺序节点 znode,一次一个,位于 /phrases/distributor/{TARGET_ID}/partitions/{PARTITION}/nodes/ znode。如果创建的 znode 是第一个 R znode 之一(R 是每个分区的副本节点数【11】),继续执行下一步。否则,从这个分区移除 znode 并尝试加入下一个分区。

b. 备用后端节点从 /phrases/5_tries/{TARGET_ID}/{PARTITION} 获取序列话的 Trie 文件,并开始将 Trie 加载到内存中。

c. 当 Trie 加载到内存时,备用后端节点通过将 /phrases/distributor/{TARGET_ID}/partitions/{PARTITION}/nodes/{CREATED_ZNODE} znode 设置为后端主机名,将自己标记为就绪。

2、Trie 后端应用程序服务轮询 /phrases/distributor/{TARGET_ID}/ sub-znode ( TARGET_ID 是 /phrases/distributor/next_target 中定义的节点),并检查是否所有分区的所有节点都标记为就绪。

a. 如果它们都为下一个 TARGET_ID 做好了准备,那么服务将在单个事务中将 /phrases/distributor/next_target znode 的值更改为空,并将 /phrases/distributor/current_target znode 设置为新的 TARGET_ID 。通过这一步骤,所有标记为就绪的备用后端节点现在都将处于活动状态,并将用于以下分发服务器请求。

分发服务器:处理热门短语的请求

当分发服务器的后端节点处于活动状态并加载了它们各自的尝试后,我们就可以开始为给定的前缀提供热门短语请求:

1、客户端通过 http://localhost:80/top-phrases?prefix="some prefix" 向网关请求给定前缀的热门短语。

2、网关通过 http://distributor.load-balancer:5000/top-phrases?prefix="some prefix" 将此请求发送到分发服务器的负载均衡器。

、3 负载均衡器通过 http://distributor.frontend:8000/top-phrases?prefix="some prefix" 将请求转发到其中一个前端。

4、前端服务器处理请求:

a. 前端服务检查分布式缓存(redis)是否有这个前缀的条目【12】。如果是,则返回这些缓存的热门短语,否则,继续执行下一步。

b. 前端服务从 zookeeper( /phrases/distributor/{TARGET_ID}/partitions/ znode)获取当前 TARGET_ID 的分区,并选择与提供的前缀匹配的分区。

c. 前端服务从 /phrases/distributor/{TARGET_ID}/partitions/{PARTITION}/nodes/ znode 中随机选择一个 znode,并获取其主机名。

d. 前端服务通过 http://{BACKEND_HOSTNAME}:8001/top-phrases="some prefix" 从选定的后端请求热门短语。

e. 后端使用其相应的加载 Trie 返回给定前缀的热门短语列表。

f. 前端服务将热门短语列表插入到分布式缓存(缓存模式)中,并返回热门短语。

  1. 热门短语“响应”向用户提供。

Zookeeper Znode 结构

注意:当系统运行时,请使用 shell 命令 docker exec -it zookeeper ./bin/zkCli.sh 查看当前 Zookeeper 的 znode。

  • phrasesdistributorassemblerlast_built_target - 设置为 TARGET_IDdistributorcurrent_target - 设置为 TARGET_IDnext_target - 设置为 TARGET_ID{TARGET_ID} - 例如,20200728_2241partitions|{partition 1 end}trie_data_hdfs_path - 保存序列化的 Trie 的 HDFS 路径nodes000000000000000000010000000002…{partition 2 start}|{partition 2 end} * …{partition 3 start}| * …

HDFS 文件夹结构

注意:当系统运行时,在浏览器中访问 http://localhost:9870/explorer.html 来浏览当前的 HDFS 文件和文件夹。

  • phrases1_sink - 搜索到的短语被转储到此处,分成 30 分钟的时间块。{e.g 20200728_2230}{e.g 20200728_2300}2_with_weight - 应用初始权重的短语,除以时间块。{TARGET_ID}3_with_weight_merged - 所有时间块的合并:具有最终权重的短语。{TARGET_ID}4_with_weight_ordered - 按权重递减顺序排列的单个短语文件。{TARGET_ID}5_tries - 序列化 Trie 的存储。{TARGET_ID}|{partition 1 end}{partition 2 start}|{partition 2 end}{partition 3 start}|

客户端交互

你可以通过在浏览器中访问 http://localhost 与系统进行交互。当你输入一个查询时,系统会提供搜索建议,可以通过提交更多搜索来输入更多查询或短语到系统中。

开发者手撸类谷歌搜索关键字智能匹配功能系统

 

源代码

你可以在 https://github.com/lopespm/autocomplete 上获得完整的源代码。

尾注

【1】 因为这个实现的主要目标是以简单的方式构建和共享系统,所以使用 Docker compose 代替了像 Kubernetes 或 Docker Swarm 这样的容器编排工具。

【2】 搜索查询的平均长度为 2.4 个词,英语中的平均词长为 4.7 个字符。

【3】 在本文中, 短语 和 查询 是可以互换使用。不过,在系统内部中,只使用 短语 这一术语。

【4】 在这个实现中,为清楚起见,只使用了代理的一个实例。但是,对于大量的传入请求,最好将该主题分为多个实例(消息将根据 短语 键进行分区),以便分配负载。

【5】 ** /phrases/1_sink/phrases/{30 minute window timestamp} 文件夹 :例如,假设消息 A[time: 19h02m] [time: 19h25m],C[time: 19h40m],消息 A 和 B 将放入文件夹 /phrases/1_sink/phrases/20200807_1900,而消息 C 将被放入文件夹 /phrases/1_sink/phrases/20200807_1930。

【6】 在将这些消息传递给 Hadoop 之前,我们还可以将它们预先聚合到另一个主题中(使用 Kafka Streams)。

【7】 为清楚起见,在这个实现中,MapReduce 作业是通过 make do_mapreduce_tasks 手动触发的,但是在生产环境中,它们可以通过 cron job 每 30 分钟触发一次。

【8】 可以添加一个额外的 MapReduce 来将 /phrases/1_sink/phrases/ 文件夹聚合为更大的时间 timespan 聚合(如 1 天,5 周,10 天等)。

【9】 可在 assembler/hadoop/mapreduce-tasks/do_tasks.sh 中通过变量 MAX_NUMBER_OF_INPUT_FOLDERS 进行配置。

【10】 分区在 assembler/trie-builder/triebuilder.py 中定义。

【11】 每个分区的副本节点数是通过 docker-compose.yml 中的环境变量 NUMBER_NODES_PER_PARTITION 配置的。

【12】 在这个实现中,默认情况下分布式缓存是禁用的,因此,对于首次使用这个代码库的人来说,可以更清楚地了解每个更新 / 步骤中发生了什么。分布式缓存可以通过 docker-compose.yml 中的环境变量 DISTRIBUTED_CACHE_ENABLED 来启用。

原文链接:

https://lopespm.github.io/2020/08/03/implementation-autocomplete-system-design.html



Tags:谷歌   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
我们所见过的技术上最复杂的漏洞利用之一”- 谷歌“零号项目”安全研究人员评价ForcedEntry无交互攻击。多年来,以色列间谍软件开发商NSO集团针对安卓和iOS设备开发出了多款...【详细内容】
2021-12-24  Tags: 谷歌  点击:(8)  评论:(0)  加入收藏
博雯 发自 凹非寺量子位 报道 | 公众号 QbitAI在炼丹过程中,为了减少训练所需资源,MLer有时会将大型复杂的大模型“蒸馏”为较小的模型,同时还要保证与压缩前相当的结果。这就...【详细内容】
2021-12-24  Tags: 谷歌  点击:(9)  评论:(0)  加入收藏
谷歌访问助手插件是专门针对chrome谷歌浏览器而开发的一款访问插件,可以为谷歌搜索,谷歌chrome商店,gmail邮箱提供加速服务,解决打不开的问题。这款插件可以帮助我们在使用谷歌...【详细内容】
2021-12-03  Tags: 谷歌  点击:(12)  评论:(0)  加入收藏
最近发现B2B的海外推广貌似是一个挺大的缺口,很多厂长或老板不了解独立站的流量构成和玩法,无论是自然流量还是付费流量。也衍生了很多培训(咦,这是不是我副业的好机会?)所以这次...【详细内容】
2021-11-11  Tags: 谷歌  点击:(32)  评论:(0)  加入收藏
如果你是一名忠实的Android玩家,那么可能会知道,今年的Android 12系统在版本规划上与“往届”相比可以说是很有些特殊。具体来说,除了前段时间刚刚推出正式版的Android 12外,谷...【详细内容】
2021-11-10  Tags: 谷歌  点击:(23)  评论:(0)  加入收藏
本月 12 日,谷歌召开了 Google Cloud Next &#39;21 年度大会。在这场大会上,谷歌宣布推出Google Distributed Cloud(谷歌分布式云计算),这是一套软硬件结合的解决方案,用于将谷歌...【详细内容】
2021-10-29  Tags: 谷歌  点击:(29)  评论:(0)  加入收藏
谷歌新推出了弱监督看图说话模型SimVLM,能够轻松实现零样本学习(zero-shot)任务迁移。...【详细内容】
2021-10-27  Tags: 谷歌  点击:(40)  评论:(0)  加入收藏
由于一些特殊原因,使用国内手机号码注册谷歌邮箱会有各种限制,最常见的一种就是此电话号码无法用于进行验证,这就让人很无语了,很多朋友都卡在了这里。本期就针对国内手机号码注...【详细内容】
2021-10-27  Tags: 谷歌  点击:(38)  评论:(0)  加入收藏
很多人在使用谷歌浏览器时都有多开的需求,但是google浏览器是不支持多开的,只能切换账户。更不要提每个多开的窗口都配置不同的ip了。如果想要实现谷歌浏览器分身单窗口单IP,其...【详细内容】
2021-10-22  Tags: 谷歌  点击:(187)  评论:(0)  加入收藏
今天凌晨,谷歌正式发布了全新一代安卓Android 12系统,拥有全新的UI,同时带来了六大新功能,除此以外还有10月的安全补丁,下面就给大家介绍这六大新功能以及安卓Android 12系统配置...【详细内容】
2021-10-22  Tags: 谷歌  点击:(53)  评论:(0)  加入收藏
▌简易百科推荐
今天不讲信息流,讲点其他的,比如搜索搜索是什么东西?见过开店卖东西吧,原理大同小异。比如我在步行街租个店铺,开个鞋店,每天在店里等着来步行街的人进我店里买我的鞋。百度搜索就...【详细内容】
2021-12-24  运营王明皓    Tags:搜索   点击:(9)  评论:(0)  加入收藏
在过去的时间中,我写了比较多的关于谷歌SEO推广,今天来写写GoogleAds广告账户免费诊断分析。今天我们的主题是:如何借助GoogleAds广告账户免费诊断分析工具,来诊断并优化你的Goo...【详细内容】
2021-10-26  优易化海外营销推广    Tags:GoogleAds   点击:(43)  评论:(0)  加入收藏
霸屏通俗来讲就是霸占屏幕,百度霸屏就是在百度搜索的结果中,除了竞价内容,剩下的都是我们品牌词或网站的内容。以用户的搜索习惯来说,一般翻两三页就不会再继续翻下去了。所以我...【详细内容】
2021-10-22  聪少爱学堂    Tags:霸屏引流   点击:(50)  评论:(0)  加入收藏
网络推广计划表示在网站优化时,内容优化也是重中之重,其中有关文章的优化也让站长们苦恼不已,因为不太清楚蜘蛛对网站文章的质量评判是如何的,很难做到更精准的蜘蛛“取向”,那么...【详细内容】
2021-10-22  云霸屏    Tags:搜索引擎   点击:(45)  评论:(0)  加入收藏
我们在做SEO优化的过程中,通常都会用到百度站长平台、5118、站长工具等seo工具,用来分析查询关键词排名。特别是百度站长平台中的分析数据很多,其中百度站长工具中的流量与关键...【详细内容】
2021-10-22  双丝网络    Tags:百度站长平台   点击:(35)  评论:(0)  加入收藏
网络推广费用了解到,网站关键词排名效果想要更好,就要扎实的做好优化工作。关键词排名高的网站能更优秀的出现在搜索引擎首页,获得更多的用户浏览,得到更高的权重,从而给企业带来...【详细内容】
2021-09-25  云霸屏  搜狐号  Tags:蜘蛛   点击:(39)  评论:(0)  加入收藏
百度搜索贸易风算法,消除了使用翻页键诱导用户行为,简单地告诉我们,只要你的翻页按钮存在异常跳转行为,无论跳转到哪个页面,都属于该算法的覆盖范围。百度的搜索交易风算法主要攻...【详细内容】
2021-08-31  羽西223    Tags:信风算法   点击:(66)  评论:(0)  加入收藏
1 前言现今互联网上的很多产品、战略决策都由数据驱动,以BulletTech为例,在运营微信公众号时,通过后台数据我们对每篇文章都会进行流量来源、裂变和阅读完关注等重要指标的监控...【详细内容】
2021-08-02  BulletTech    Tags:Google Analytics   点击:(94)  评论:(0)  加入收藏
昨晚松松编辑杰哥了解到,百度搜索最近对算法更新了,全面升级“蓝天算法”2.0版本,主要针对高权重网站出租二级目录和二级域名行为,这是要开始加大清洗目录出租站点了吗? 根据杰...【详细内容】
2021-07-29  卢松松    Tags:蓝天算法   点击:(76)  评论:(0)  加入收藏
网罗天下谈运营2021-07-20在做SEO的过程中,对于企业主而言,没有人刚开始建立网站的时候就会先知先觉,采用完全正确的SEO优化方法,这很必然会导致一些问题,比如:① 站内目录层级繁...【详细内容】
2021-07-21  Lollipop    Tags:网站不收录   点击:(81)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条