Elasticsearch:搜索架构

Elasticsearch

全文检索的复杂性

为了理解为什么全文搜索是一个很难解决的问题,让我们想一个例子。 假设你正在托管一个博客发布网站,其中包含数亿甚至数十亿的博客文章,每个博客文章包含数百个单词,类似于 CSDN。

执行全文搜索意味着任何用户都可以搜索 “java” 或 “学习编程” 之类的内容,并且你需要在几毫秒内找出出现这些单词的所有博客文章。 不仅如此,你还需要根据多种因素对这些博客文章进行评分,例如,这些单词在这些帖子中出现的频率,或者每个帖子有多少拍手或评论,或者你可能想在顶部显示最近写的帖子,或者你可能想突出显示某些顶级内容创建者,或者你可能想将这些单词出现在标题中的帖子放在更高的位置,等等。

另外,你知道用户可能会意外地犯错,因此你需要处理这个问题。 你还需要考虑单词的顺序,“学习 Java” 应该与 “Java 学习” 具有相似的含义,但有时顺序会更重要,例如 “二氧化碳” 可能与 “化碳二氧” 有很大不同 ”(这只是一个例子,我不知道这是不是一个词,我不懂化学)。

仅仅匹配单词也是行不通的。 有些词比其他词为帖子提供了更多的上下文。 例如,当用户搜索 “Java” 时,标题为 “学习 Java” 的博客文章是相关结果,但当用户仅搜索 “学习” 时,相关性就不那么高了。 当用户搜索 “编程” 时,这也是一篇相关的博客文章,即使该词从未出现在博客文章中!

这些挑战极其复杂,乍一看,它们似乎几乎无法搜索,但你打开一个订餐应用程序,在数千家餐厅的数万种菜肴中进行搜索,或者搜索执行特定工作的人员 每天在 Linkedin 上数亿用户中发挥作用,或在数十亿博客文章中搜索特定主题。

Elasticsearch 是一个旨在解决这个问题的数据库。 让我们看看它是如何工作的。

理解术语

在开始使用 Elasticsearch 之前,我们应该先熟悉一下术语。 为了更好地理解事情,让我们举个例子。 假设你在 Elasticsearch 上存储博客文章。

Nodes

节点只是单独的 Elasticsearch 进程。

通常,你会在每台机器上运行一个 Elasticsearch 进程,因此更容易将它们视为单独的服务器。 这些进程中的每一个都独立于其他进程运行,并且仅通过公共网络连接。 Elasticsearch 通常作为大型分布式系统运行,这意味着你通常会运行多台机器(或节点)。

一旦所有这些节点一起运行,它们就可以形成一个“集群 (cluster)”。 集群不仅仅是各个部分的总和; 它不仅仅是一定数量的孤立运行的节点。 相反,节点知道它们是集群的一部分,并在执行不同操作时相互通信。 在某种程度上,Elasticsearch 集群是一个全新的实体。

Elasticsearch 集群有大量的职责,例如存储文档、搜索这些文档、执行不同的分析和聚合任务、备份数据等。它还必须进行自我管理,例如确保哪些节点是健康的,哪些节点是健康的 因此,在任何大型集群中,为不同的操作域提供不同的节点非常重要。

虽然可能存在许多这样的区别,但其中一个明显的区别是存储数据并执行繁重的数据密集型任务的节点,例如搜索和拥有管理集群的专用节点、确保节点健康、决定将哪个文档发送到哪个节点等。创建这种区别很重要,因为这些节点甚至可能需要不同的硬件资源。 数据节点可能需要更大的机器,具有更高性能的网络和磁盘以及大量内存,而执行更多管理任务的节点可能有完全不同的要求。

存储数据和搜索的节点可以是 “数据 (data)” 节点,执行更多管理任务的节点可以称为 “主 (master)” 节点。

有关节点的更多描述,请阅读文章 “Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica”。事实上,除了 data 及 master 节点之外,Elasticsearch 还有其它类型的节点。

索引和文档

文档是你存储在 Elasticsearch 中的简单 JSON 对象。 它们与关系数据库中的行或 MongoDB 中的单个文档同义。

对于我们的示例,单个文档可能如下所示 -

{"_id": "9a91473c-522e-4174-bf7f-f55293b8e526","post_title": "Learning about Elasticsearch","author_name": "Zhang san",.....
}

索引是相似文档的集合。 它们与关系数据库中的表(其中每一行都是单个项目)和 MongoDB 中的集合同义。

因此,对于我们的示例,我们将有一个存储博客文章的索引。 我们称之为 blog_posts。 如果我们想存储一些其他数据,比如说用户,我们可以创建另一个索引,用户。 blog_posts 索引存储各种博客文章文档,每个文档都包含与博客文章相关的字段,而 users 索引存储包含 user_name、email 等字段的用户文档。

Shards - 分片

索引中的文档被分为多个分片。 每个分片存储索引文档的某个子集。 稍后我们会理解为什么将文档划分为多个分片很重要,但现在我们先关注分片的工作原理。

例如,假设我们有一些 blog_posts 文档。

如果我们为此索引创建三个分片(例如分片 A、分片 B、分片 C),那么我们所有的文档都将分为这三个分片。

然后,这些分片将驻留在集群中的不同数据节点中。

这很重要,因为将这些文档分布到多个分片中可以为你带来多种优势,

  1. 搜索可以并行化。 当用户想要执行搜索时,将搜索所有文档。 如果在单个服务器上搜索所有文档,这将非常耗时。 分片允许你将文档分布在多个服务器上,从而允许在不同的硬件上并行执行单个搜索。
  2. 其他查询,例如插入文档(在 Elasticsearch 中称为索引)或通过特定 ID 检索文档,将分布在所有节点之间。

然而,我们的架构仍然不完整。 如果一个节点死亡,它存储的分片(以及这些分片上的数据)将永远丢失。

让我们看看主分片 (primary shard) 和副本分片 (replica shard) 以更好地理解这一点。

主分片、副本分片和不同分片(distinct shards)

只是对到目前为止我们已经介绍过的内容的快速修订:单个分片包含多个文档。 例如,

每个分片都位于一个特定的节点上,

到目前为止,我们架构的一个问题是,如果某个特定节点(假设 10.192.0.3)挂掉或变得不可用,“分片 A”中的数据将永远丢失。 为了解决这个问题,我们引入 “副本分片” 和 “主分片” 的概念。 主分片是我们到目前为止一直在讨论的分片(现在将它们标记为“主(Primary)”),

副本分片 (replica shards) 是仅存储主分片与存储关联的相同文档的分片。 因此,副本分片只是 “复制” 或复制特定的主分片。

在上图中,你可以看到每个主分片都有一个关联的副本分片,并且每个副本分片存储与主分片相同的文档。 在这里,我们每个主分片有一个副本分片,但我们也可以将这个数字修改为更大 —— 每个主分片可以有两个副本。 现在,我们继续每个主分片一个副本。

这些副本分片不需要与主分片位于同一节点上(每个副本位于与其主分片不同的节点上是有意义的)。 主分片和副本分片都分布在集群的所有节点上。

在上图中,每个分片的主分片和副本分片存在于不同的节点上。 单节点故障不会导致数据不可用。 例如,如果节点 10.192.0.3 不可用,则分片 A 和分片 B 的数据都不会丢失。 分片 A 的数据在节点 10.192.0.2 上仍然可用,同样,分片 B 的数据在节点 10.192.0.1 上仍然可用。

这意味着我们的集群可以在单个节点丢失的情况下幸存下来。 然而,我们的集群可能无法在失去两个节点的情况下幸存下来。 例如,10.192.0.3 和10.192.0.2 节点同时丢失将导致分片 A 的文档完全不可用。 我们可以配置更高的复制,例如,每个主分片使用两个副本来缓解这种情况。 但现在,我们继续每个主分片一个副本。

最后,我们来看看 “不同分片(distinct shards)”。 不同分片只是一个术语,用于将相同的主分片和副本分组在一起。 因此,在我们当前的示例中,我们有三个主分片、三个副本分片(每个主分片 1 个副本)、六个总分片(三个主分片 + 三个副本)和三个不同的分片,

将主分片及其相应的副本分片分组为单个 “不同分片” 如此重要的原因将会变得清晰。 重申一下,“不同分片” 只是分片的逻辑分组,并且确实影响了我们到目前为止所绘制的架构。

我们来看几个真实的查询示例

为了结束架构讨论,让我们看看搜索查询和获取查询在我们的示例集群中如何工作。

第一步…

让我们看看执行搜索或获取查询时会发生什么。

这就是我们集群现在的样子,

客户端 API 向这些节点中的任何一个发送搜索或获取查询。 它发送查询的节点成为 “协调器(coordinator)” 节点。 更大的集群甚至可能有专用的协调器节点(专用协调器节点是不具有任何节点角色的节点,它只可以接收客户端的请求),但我们现在不需要这样做。在文章的开始部分,我们可以看到一个更为详细的架构图。

该协调器节点负责接收请求、与其他节点通信(如果需要)、组合从多个节点接收到的结果并返回结果。

搜索

搜索时,搜索查询必须命中所有不同的分片。 这是因为所有分片都使用它们所保存的文档单独在本地执行搜索。

然后,协调器节点将与多个节点通信,以从每个不同的分片获取数据。 回想一下,在我们的示例中,每个主分片有一个副本,因此查询仅命中集群中的一半分片(主分片或副本分片)。

有关详细的如何完成一个请求,请阅读文章 “Elasticsearch:数据是如何被读取的?”。

根据 id 来进行查询

当通过 ID 对特定文档执行查询时,协调器节点已经知道哪个分片将保存该文档,因此无需命中所有节点。 它只是将请求转发到存储数据的节点并将响应发送回客户端。这是因为每当一个文档进来后,根据文档的 id 会自动进行 hash 计算,并存放于计算出来的 shard 实例中,这样的结果可以使得所有的 shard 都比较有均衡的存储,而不至于有的 shard 很忙。

shard_num = hash(_routing) % num_primary_shards

我们可以根据文档的 id 来计算出来是哪一个 shard。

结论

这是对 Elasticsearch 架构的非常简单的介绍。希望大家能对 Elasticsearch 的集群架构有一个比较清楚的认识。更多关于 Elasticsearch 的术语及概念介绍,请详细阅读文章 “Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/182978.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Unity细节】为什么UI移动了锚点,中心点和位置,运行的时候还是不在设置的位置当中

👨‍💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 😶‍🌫️收录于专栏:unity细节和bug 😶‍🌫️优质专栏 ⭐【…

数据约束及增删改查(CRUD)进阶-MySQL

文章目录 一、数据库约束1.1 约束类型1.2 NULL约束1.3 UNIQUE:唯一约束1.4 DEFAULT:默认值约束1.5 PRIMARY KEY:主键约束1.6 FOREIGN KEY:外键约束1.7 CHECK 约束(了解) 二、表的设计2.1 一对一2.2 一对多2…

kimera论文阅读

功能构成: Kimera包括四个关键模块: Kimera-VIO的核心是基于gtsam的VIO方法[45],使用IMUpreintegration和无结构视觉因子[27],并在EuRoC数据集上实现了最佳性能[19]; Kimera-RPGO:一种鲁棒姿态图优化(RPGO)方法,利用现代技术进…

代码随想录 Day38 完全背包问题 LeetCode T70 爬楼梯 T322 零钱兑换 T279 完全平方数

前言 在今天的题目开始之前,让我们来回顾一下之前的知识,动规五部曲 1.确定dp数组含义 2.确定dp数组的递推公式 3.初始化dp数组 4.确定遍历顺序 5.打印dp数组来排错 tips: 1.当求取物品有限的时候用0-1背包,求取物品无限的时候用完全背包 结果是排列还是组合也有说法,当结果是组…

vue 实现在线预览Excel-LuckyExcel/LuckySheet实现方案

一、准备工作 1. npm安装 luckyexcel npm i -D luckyexcel 2.引入luckysheet 注意:引入luckysheet,只能通过CDN或者直接引入静态资源的形式,不能npm install。 个人建议直接下载资源引入。我给你们提供一个下载资源的地址: …

JVM虚拟机:垃圾回收器之Parallel Scavenge

本文重点 在前面的课程中,我们学习了新生代的串行化垃圾回收器Serial,本文我们将学习新生代的另外一个垃圾回收器Parallel Scavenge(PS),PS是一个并行化的垃圾回收器,它使用复制算法来清理新生代的垃圾。 运行方式 如上所示,当进行垃圾回收的时候,它会暂停工作线程,而…

【图像分类】【深度学习】【Pytorch版本】AlexNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】AlexNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】AlexNet模型算法详解前言AlexNet讲解卷积层的作用卷积过程特征图的大小计算公式Dropout的作用AlexNet模型结构 AlexNet Pytorch代码完整代码总结 前言 AlexNet是…

Mac电脑录屏软件 Screen Recorder by Omi 中文最新

Screen Recorder by Omi是一款屏幕录制软件,它可以帮助用户轻松地录制屏幕活动,并将其保存为高质量的视频文件。 该软件提供了多种录制选项,包括全屏录制、选择区域录制和单窗口录制等,同时提供了丰富的设置选项,如视…

数据集划分:手动划分文件夹中的图片数据集为训练集、验证集和测试集

1.需求 手动划分文件夹中的图片数据集为训练集、验证集和测试集,即进行文件夹中的数据集(都是图片)进行划分。 2.步骤 使用文件处理库(如os)遍历读取文件夹中的图片文件。将读取到的图片文件路径存储到列表中。打乱…

Golang源码分析之golang/sync之singleflight

1.1. 项目介绍 golang/sync库拓展了官方自带的sync库,提供了errgroup、semaphore、singleflight及syncmap四个包,本次分析singlefliht的源代码。 singlefliht用于解决单机协程并发调用下的重复调用问题,常与缓存一起使用,避免缓存…

〔001〕虚幻 UE5 安装教程

✨ 目录 🎈 下载启动程序🎈 注册个人账户🎈 选择引擎版本🎈 选择安装选项🎈 虚幻商城的使用🎈 每月免费插件🎈 安装插件🎈 下载启动程序 下载地址:https://www.unrealengine.com/zh-CN/download点击上面地址,下载 UE5 启动程序并安装🎈 注册个人账户 打开商…

用Rust和Scraper库编写图像爬虫的建议

本文提供一些有关如何使用Rust和Scraper库编写图像爬虫的一般建议: 1、首先,你需要安装Rust和Scraper库。你可以通过Rustup或Cargo来安装Rust,然后使用Cargo来安装Scraper库。 2、然后,你可以使用Scraper库的Crawler类来创建一个…

Nginx默认会自动忽略请求头Headers里带下划线_的参数

起因:该接口设置了必须要传送app_code和app_secret才能正常访问。实际我在本地环境测试中,发现该接口是正常访问的,但是部署到正式系统之后发现,该接口一直提示app_code和app_secret不能为空。 后续排查:发现正式系统…

「Verilog学习笔记」位拆分与运算

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 1、寄存器的位是可以分开单独运算的,并不是一个输入就一定是一个数据,在很多情况下,一个输入既包括数据又包括地址等其他有效信息 2、需…

jsonlite库

jsonlite是一个R语言中用于处理JSON数据的库。它提供了一组简单而强大的函数,用于解析、生成和转换JSON数据。 使用jsonlite库,您可以轻松地将JSON数据解析为R语言中的数据结构,如列表或数据框。您还可以将R语言中的数据结构转换为JSON格式&…

网络协议的基本概念

网络协议的基本概念 随处可见的协议 在计算机网络与信息通信领域里,人们经常提及“协议”一词。互联网中常用的具有代表性的协议有IP、TCP、HTTP等。 “计算机网络体系结构”将这些网络协议进行了系统归纳。TCP/IP就是IP、TCP、HTTP等协议的集合。现在&#xff0…

卡尔曼滤波之二:Python实现

卡尔曼滤波之二:Python实现 1.背景描述2.构建卡尔曼滤波公式2.1 预测2.2 更新 3.代码实现3.1 输入值3.2 pykalman包实现3.3 不使用Python包实现3.4 效果可视化 参考文献 了解了卡尔曼滤波之一:基本概念,可以结合代码来理解下卡尔曼滤波的2个预…

3.27每日一题(常系数线性非齐次方程的特解)

常系数非齐次线性方程的特解如何假设(两种)形式: 1、题目中 e 的 x 次幂以及 1,都是第一种:1可以看成为e的0次幂 注:题目给的多项式是特殊的形式,我们要设为一般的形式的多项式 2、题目中sin…

Python 爬虫基础

Python 爬虫基础 1.1 理论 在浏览器通过网页拼接【/robots.txt】来了解可爬取的网页路径范围 例如访问: https://www.csdn.net/robots.txt User-agent: * Disallow: /scripts Disallow: /public Disallow: /css/ Disallow: /images/ Disallow: /content/ Disallo…