Elasticsearch入门篇
1.介绍 Elasticsearch
1.1.什么是 Elasticsearch?
Elasticsearch 是一种开源的搜索和分析引擎,专门用于处理大规模的数据,并以非常快的速度进行搜索和分析。它基于一个叫做 Apache Lucene 的库构建,但与 Lucene 相比,Elasticsearch 提供了更多的功能和易用性,使其成为处理和分析数据的强大工具。
1.1.1.简单理解 Elasticsearch
想象一下,你有一大堆书,而你需要在这些书中找到某个特定的词或一句话。如果你逐页翻阅,这将是一个非常耗时的过程。Elasticsearch 就像一个超级快速的图书馆管理员,它能在瞬间找到你想要的内容,不管这些书有多少。
1.1.2.核心概念
-
开源与分布式
- 开源:Elasticsearch 是开源的,这意味着它的代码是公开的,任何人都可以使用和修改它。开源社区的力量使得 Elasticsearch 不断改进和更新。
- 分布式:Elasticsearch 能够运行在多台服务器上,并把数据分布存储在这些服务器上。这种设计使它能够处理非常大的数据集,并且即使一台服务器出现问题,其他服务器仍然可以继续工作。
-
基于 Apache Lucene
- Lucene 是一个非常强大的搜索库,但直接使用 Lucene 需要编写大量代码。Elasticsearch 使 Lucene 变得更容易使用,提供了一个简单的接口和许多额外的功能,使构建搜索和分析应用程序变得更加简单。
-
近实时(Near Real-Time)搜索
- Elasticsearch 的一个重要特点是它的近实时搜索能力。当数据被存储到 Elasticsearch 中后,几乎立即就可以被搜索到。这对需要处理和分析实时数据的应用非常有用,比如日志监控系统。
1.1.2.1.主要功能
-
全文搜索
- Elasticsearch 能够快速高效地处理全文搜索。这意味着它不仅仅能够搜索关键词,还能处理复杂的查询,比如匹配短语、布尔查询(与或非)、范围查询等。
-
数据分析
- 除了搜索,Elasticsearch 还能够对数据进行深入分析。它提供了强大的聚合功能,允许你进行各种统计分析,比如求平均值、最大值、最小值、分布情况等。
-
实时数据处理
- Elasticsearch 可以处理和分析实时数据。这使得它非常适合用于日志分析和监控系统。通过与其他工具(如 Beats 和 Logstash)的集成,可以从各种数据源收集数据,并实时发送到 Elasticsearch 进行分析。
-
扩展性和高可用性
- 由于其分布式架构,Elasticsearch 可以轻松扩展以处理更多的数据和查询负载。你只需增加更多的服务器节点,就能提升其处理能力。此外,Elasticsearch 通过分片和副本机制确保数据的高可用性和容错能力。
1.1.3.应用场景
-
日志和事件数据分析
- Elasticsearch 经常用于收集和分析日志数据。通过与 Kibana(一个可视化工具)的结合,可以创建直观的仪表盘,帮助用户实时监控和分析系统日志,快速发现和解决问题。
-
全文搜索
- 许多网站和应用程序使用 Elasticsearch 作为其搜索引擎,提供快速和精准的全文搜索功能。例如,电商网站可以使用 Elasticsearch 让用户快速找到他们想要购买的商品。
-
监控和安全分析
- Elasticsearch 也用于实时监控和安全分析。通过收集和分析系统日志、网络流量等数据,可以实时监控系统运行状态,并检测和响应潜在的安全威胁。
-
数据存储和检索
- 除了搜索和分析,Elasticsearch 还可以作为一个高效的数据存储和检索系统,特别适合需要快速访问的大规模数据集。
1.2.为什么选择 Elasticsearch?
Elasticsearch 是一个强大的搜索和分析引擎,广泛应用于各种场景。它的受欢迎程度源于其诸多优势和特点,使其成为许多企业和开发者在处理大规模数据和实时搜索需求时的首选。下面,我们将详细介绍为什么选择 Elasticsearch 以及它的主要优点。
1.2.1 快速的全文搜索能力
Elasticsearch 基于 Apache Lucene 构建,具备极快的全文搜索能力。这意味着无论是查找单个关键词、短语,还是执行复杂的布尔查询,Elasticsearch 都能够迅速返回结果。这对需要处理大量文本数据的应用场景非常重要,比如:
- 电商网站:快速查找商品并提供精准的搜索结果,提高用户体验。
- 内容管理系统:高效地检索文章、博客和文档中的信息。
1.2.2. 实时数据处理
Elasticsearch 的近实时搜索能力使其非常适合处理实时数据。这意味着当新数据被存储到 Elasticsearch 中后,几乎立即就可以被搜索和分析。这一特点在以下场景中尤为关键:
- 日志和监控系统:实时分析系统日志,快速发现和解决问题。
- 安全监控:实时监测和分析安全事件,及时检测和响应潜在威胁。
1.2.3. 分布式架构和可扩展性
Elasticsearch 的分布式设计使其能够在多个服务器节点上运行,并将数据分布存储在这些节点上。这种架构带来了巨大的扩展性和容错能力:
- 扩展性:随着数据量和查询量的增加,可以通过添加更多节点来线性扩展系统的存储和处理能力。
- 高可用性:即使某个节点出现故障,其他节点仍然可以继续工作,确保系统的持续运行。
1.2.4. 强大的数据分析功能
除了搜索,Elasticsearch 还提供了强大的数据分析能力。通过聚合功能,可以对数据进行复杂的统计分析。这对需要从大量数据中提取有价值信息的场景非常有用:
- 数据分析:计算平均值、最大值、最小值、分布情况等,帮助做出数据驱动的决策。
- 商业智能:分析用户行为、销售数据等,为业务发展提供洞察。
1.2.5. 易用的 RESTful API
Elasticsearch 提供了丰富的 RESTful API,使得与其交互变得非常简单。无论是索引数据、执行搜索查询,还是进行集群管理,都可以通过简单的 HTTP 请求完成。这对于开发者来说,非常友好:
- 开发便捷:无需复杂的设置和配置,通过简单的 API 调用即可实现强大的功能。
- 集成简单:容易与其他系统和应用集成,例如使用 Logstash 收集数据、使用 Kibana 进行数据可视化。
1.2.6. 活跃的社区和丰富的生态系统
Elasticsearch 是一个开源项目,拥有一个非常活跃的社区。你可以从社区获得大量的支持和资源,包括文档、教程、插件等。此外,Elasticsearch 还拥有丰富的生态系统:
- Beats:轻量级数据采集器,用于将数据发送到 Elasticsearch。
- Logstash:数据处理管道,支持从多种来源收集、转换和加载数据到 Elasticsearch。
- Kibana:强大的可视化工具,可以创建各种仪表盘和图表,直观展示数据分析结果。
1.2.7. 企业级功能
对于需要高性能和高可靠性的企业应用,Elasticsearch 还提供了一些高级功能,例如:
- 安全性:通过 X-Pack 提供的安全功能,可以实现用户身份验证、访问控制和数据加密,确保数据安全。
- 监控和报警:可以监控集群的运行状态,设置报警机制,在出现问题时及时通知管理员。
1.3.Elasticsearch 的特点与优势
Elasticsearch 是一个功能强大且灵活的搜索和分析引擎。它不仅仅是一个搜索工具,更是一个能够处理大规模数据、提供实时分析的综合解决方案。
1.3.1. 分布式架构
分片和副本
Elasticsearch 采用分布式架构设计,数据被分成多个分片(shards)并分布存储在多个节点上。每个分片可以有一个或多个副本(replicas),以提高数据的可用性和容错性。
- 分片:将数据分成更小的块,分布在集群中的不同节点上,提高查询和索引的性能。
- 副本:每个分片可以有多个副本,分布在不同节点上,确保数据的高可用性和容错性。
这种分布式设计使得 Elasticsearch 能够轻松扩展,通过增加节点来处理更多的数据和更高的查询负载。
1.3.2. 近实时搜索
Elasticsearch 的一个显著特点是其近实时(Near Real-Time, NRT)搜索能力。当新数据被索引后,几乎立即就可以被搜索到。这对于需要快速处理和分析新数据的应用场景非常重要,例如日志分析和监控系统。
1.3.3. 强大的全文搜索能力
Elasticsearch 基于 Apache Lucene,具备强大的全文搜索功能。它能够处理各种复杂的查询需求,包括:
- 布尔查询:支持 AND、OR、NOT 等逻辑操作。
- 短语查询:能够搜索精确的短语匹配。
- 范围查询:支持对数值、日期等范围的查询。
- 分词器和倒排索引:通过分词器将文本分成词条,并创建倒排索引,使得全文搜索快速高效。
1.3.4. 丰富的分析功能
除了搜索,Elasticsearch 还提供了强大的数据分析功能。通过聚合(aggregation)功能,可以对大规模数据进行复杂的统计分析,例如:
- 计数:计算文档的数量。
- 求和:计算数值字段的总和。
- 平均值:计算数值字段的平均值。
- 最大值和最小值:找到数值字段的最大值和最小值。
- 直方图和分布:创建数据分布的直方图和分桶统计。
这些功能使得 Elasticsearch 不仅是一个搜索引擎,还可以作为一个强大的分析工具。
1.3.5. 灵活的 RESTful API
Elasticsearch 提供了灵活的 RESTful API,支持通过 HTTP 请求与其交互。这使得它的使用和集成变得非常简单:
- 索引数据:通过简单的 HTTP PUT 或 POST 请求将数据存储到 Elasticsearch 中。
- 执行查询:通过 HTTP GET 请求执行各种搜索查询。
- 集群管理:通过 API 进行集群的配置和管理。
这种灵活性使得开发者能够轻松地将 Elasticsearch 集成到各种应用和系统中。
1.3.6. 扩展性和高可用性
由于其分布式架构,Elasticsearch 具有很高的扩展性和高可用性:
- 线性扩展:通过增加节点,可以线性地增加存储和处理能力。
- 容错能力:通过分片和副本机制,即使某个节点出现故障,其他节点仍然可以继续工作,确保系统的高可用性。
这种设计使得 Elasticsearch 能够处理从几百兆到几百TB的数据量,适应各种规模的应用需求。
1.3.7. 安全性和权限控制
Elasticsearch 提供了多种安全功能,确保数据的安全性和访问控制:
- 身份验证和授权:通过 X-Pack 插件提供用户身份验证和基于角色的访问控制。
- 加密:支持数据在传输和存储中的加密,确保数据安全。
- 审计:记录所有访问和操作日志,方便进行安全审计和合规检查。
1.3.8. 丰富的生态系统
Elasticsearch 拥有一个丰富的生态系统,包括:
- Beats:轻量级的数据收集器,可以从各种数据源收集数据并发送到 Elasticsearch。
- Logstash:强大的数据处理管道,支持数据收集、转换和加载(ETL)操作。
- Kibana:可视化工具,提供强大的数据展示和分析功能,可以创建各种仪表盘和图表。
这些工具与 Elasticsearch 紧密集成,提供了一个完整的数据收集、处理、存储、分析和可视化解决方案。
1.3.9. 活跃的社区和持续的发展
作为一个开源项目,Elasticsearch 拥有一个活跃的社区。社区的活跃度带来了持续的发展和改进:
- 社区支持:活跃的用户社区提供了丰富的文档、教程和论坛支持,帮助新用户快速上手。
- 持续更新:开发者不断贡献新的功能和改进,使得 Elasticsearch 保持在技术的前沿。
2.Elasticsearch 核心概念与基本操作
2.1.索引与文档
(Type,注:Elasticsearch 7.0以后弃用了Type)
在了解 Elasticsearch 的过程中,索引(Index)和文档(Document)是两个最基本也是最重要的概念。理解它们的作用和关系,有助于更好地掌握如何使用 Elasticsearch 存储、搜索和分析数据。
2.1.1.什么是索引?
索引在 Elasticsearch 中是一个存储结构,用来组织和存储数据。你可以把它看作一个数据库或一个文件夹,其中包含了多个文档。每个索引都有一个唯一的名字,用于在操作数据时进行引用。
- 数据库:在传统的关系数据库中,数据库是存储表的容器。
- 索引:在 Elasticsearch 中,索引是存储文档的容器。类似于关系型数据库(MySQL)中的数据库和表的组合体。
每个索引可以包含多种类型的文档,而这些文档具有类似的结构。例如,如果你有一个包含商品信息的索引,索引中的每个文档都可能包含商品名称、描述、价格等字段。
2.1.1.1. 定义
索引在 Elasticsearch 中是一个逻辑存储单元,类似于关系型数据库中的“数据库”概念。
它是一个文档的集合,这些文档具有相似的特性或属于同一逻辑分类。
2.1.1.2. 分片与副本
索引可以包含一个或多个分片(Shards),每个分片都是一个 Lucene 实例,可以独立地进行搜索和存储操作。分片允许 Elasticsearch 在多个服务器上水平扩展,从而处理更多的数据和查询。
每个分片可以有零个或多个副本(Replicas),副本是分片的完整拷贝,用于提供数据的冗余和容错性。当某个分片所在的服务器出现故障时,可以从其副本中恢复数据。
2.1.1.3. 数据存储
索引中的文档被存储为 JSON 格式,这使得 Elasticsearch 能够存储结构化和非结构化数据。
Elasticsearch 使用倒排索引(Inverted Index)技术来实现高效的全文搜索。倒排索引将文档中的单词与其在文档中的位置信息关联起来,从而可以快速定位包含特定单词的文档。
2.1.2.什么是文档?
文档是 Elasticsearch 中的数据单位。每个文档是一组键值对(键是字段名,值是字段值),并且存储在某个索引中。文档的格式通常是 JSON 格式,这使得它非常灵活和易于使用。
- 记录:在传统的关系数据库中,表中的一行就是一条记录。
- 文档:在 Elasticsearch 中,索引中的一个文档就是一个数据条目。
例如,一个描述商品的文档可能如下:
{
"product_id": "123",
"name": "Laptop",
"description": "A high-performance laptop",
"price": 999.99,
"stock": 50
}
这个文档包含了商品的 ID、名称、描述、价格和库存量等信息。
以下是关于 Elasticsearch 文档的一些重要概念和特点:
- 结构化数据:文档是结构化的数据对象,由多个字段组成。每个字段都有一个名称和对应的值,可以是简单的数据类型(如文本、数字、日期等)或复杂的数据结构(如嵌套对象、数组等)。
- 唯一标识:每个文档都有一个唯一标识符(ID),用于在索引中唯一标识该文档。ID 可以由 Elasticsearch 自动生成,也可以由用户指定。
- 索引存储:文档被存储在索引中,每个索引可以包含多个文档。索引是文档的集合,类似于关系型数据库中的表。
- 字段映射:文档的字段映射定义了每个字段的数据类型、分析器等属性。字段映射可以手动指定,也可以由 Elasticsearch 根据插入的文档自动推断生成。
- 全文搜索:Elasticsearch 支持全文搜索,可以对文档中的文本字段进行全文检索。全文搜索可以根据关键词、词语匹配度等条件快速定位到符合条件的文档。
- CRUD 操作:文档支持 CRUD 操作,即创建(Create)、读取(Retrieve)、更新(Update)和删除(Delete)。通过 Elasticsearch 的 API 可以对文档进行增删改查操作。
- 版本控制:Elasticsearch 支持文档的版本控制,每个文档可以有多个版本。当对文档进行更新操作时,Elasticsearch 会自动创建新版本,并保存历史版本的数据。
文档是 Elasticsearch 中存储和组织数据的基本单位,具有灵活的数据模型、强大的全文搜索和分析功能,是构建分布式搜索引擎和分布式数据存储系统的核心组件之一。
2.1.3.索引与文档的关系
索引与文档的关系类似于数据库与记录(相当于 MySQL 中的行(Row))的关系。一个索引包含多个文档,而每个文档属于某个索引。
2.1.4.创建索引和文档
现在我们了解了什么是索引和文档,接下来看看如何在 Elasticsearch 中创建它们。
-
创建索引
在 Elasticsearch 中创建索引非常简单,可以使用 RESTful API 进行操作。例如,要创建一个名为 "products" 的索引,可以使用以下命令:
PUT /products
这个命令会创建一个名为 "products" 的索引,用于存储商品信息的文档。
-
添加文档
创建索引后,我们可以向其中添加文档。例如,向 "products" 索引中添加一个商品文档,可以使用以下命令
POST /products/_doc/1
{
"product_id": "123",
"name": "Laptop",
"description": "A high-performance laptop",
"price": 999.99,
"stock": 50
}
这里,_doc
是文档类型,1
是文档的 ID。如果不指定 ID,Elasticsearch 会自动生成一个唯一的 ID。
-
检索文档
要检索刚才添加的文档,可以使用以下命令
GET /products/_doc/1
这个命令会返回 ID 为 1 的文档的详细信息。
-
更新和删除文档
除了创建和检索文档外,Elasticsearch 还提供了更新和删除文档的功能。
- 更新文档
要更新现有文档,可以使用以下命令:
POST /products/_doc/1/_update
{
"doc": {
"price": 899.99,
"stock": 45
}
}
这个命令会更新 ID 为 1 的文档的价格和库存信息。
- 删除文档
要删除某个文档,可以使用以下命令:
DELETE /products/_doc/1
这个命令会删除 ID 为 1 的文档。
2.1.5.Elasticsearch与RDBMS的对应关系
我相信大家对关系型数据库(简称 RDBMS)应该比较了解,因此接下来拿关系型数据库和 ES 做一个类比,让大家更容易理解
从表中,不难看出,关系型数据库和 ES 有如下对应关系:
- 关系型数据库中的表(Table)对应 ES 中的索引(Index)
- 关系型数据库中的每条记录(Row)对应 ES 中的文档(Document)
- 关系型数据库中的字段(Column)对应 ES 中的字段(Filed)
- 关系型数据库中的表定义(Schema)对应着 ES 中的映射(Mapping)
- 关系型数据库中可以通过 SQL 进行查询等操作,在 ES 中也提供了 DSL 进行查询等操作
当进行全文检索或者对搜索结果进行算分的时候,ES 比较合适,但如果对数据事务性要求比较高的时候,会把关系型数据库和 ES 结合使用。
为了方便其他语言的整合,ES 也提供了 REST API 来给其他程序进行调用,当我们的程序要和 ES 进行集成的时候,只需要发出 HTTP 的请求就会得到相应的结果
2.2.分布式架构
TODO:分布式的详细介绍将单独发布在另一篇文章中(新文章会补充相关内容),这里只做简要概述。
Elasticsearch 是一个分布式搜索和分析引擎,这意味着它能够将数据和工作负载分布在多个节点上,以实现高性能、高可用性和可扩展性。分布式架构是 Elasticsearch 的核心特性之一,它使得 Elasticsearch 可以处理大规模数据和高并发查询。下面将以 Elasticsearch 的分布式架构,包括集群、节点、索引、分片和副本等核心概念进行介绍。
2.2.1.什么是分布式架构?
分布式架构是一种设计系统的方法,在这种方法中,系统的组件分布在多个计算机节点上,这些节点通过网络进行通信和协作。分布式架构具有以下几个显著的优点:
- 扩展性:可以通过增加更多的节点来提高系统的处理能力和存储容量。
- 高可用性:即使某个节点出现故障,系统仍然可以继续运行。
- 性能:通过将数据和查询请求分布到多个节点上,可以显著提高系统的处理速度和响应时间。
2.2.2.Elasticsearch 的分布式架构
Elasticsearch 的分布式架构由几个关键组件组成:集群、节点、索引、分片和副本。
2.2.2.1.集群
在 Elasticsearch 中,集群(Cluster)是由一个或多个节点(Node)组成的分布式系统。这些节点协同工作,共同存储、索引和搜索数据,提供高可用性、可伸缩性和容错性。集群是由一个或多个节点组成的集合,这些节点协同工作,共同存储数据并提供索引和搜索功能。每个集群都有一个唯一的名称,用于标识集群中的所有节点。集群中的所有节点通过网络相互通信,形成一个整体。
- 集群:类似于一群合作完成任务的计算机。
- 节点的集合:集群是由多个节点组成的集合。每个节点都是一个独立的 Elasticsearch 实例,可以独立运行,也可以加入到一个集群中。
- 数据分片和副本:集群中的数据被分成多个分片(Shard),每个分片可以在集群的不同节点上进行存储和复制。分片的复制称为副本(Replica),用于提高数据的可用性和容错性。
- 负载均衡:集群可以自动进行负载均衡,将搜索请求和索引请求分配到各个节点上,以实现数据的均衡存储和处理。
- 故障检测和容错:集群可以检测到节点的故障并进行处理,例如自动将丢失的分片复制到其他节点上,以确保数据的完整性和可用性。
- 主节点:集群中的主节点(Master Node)负责集群的管理和协调工作,例如分配分片、故障检测、节点加入和退出等。
- 集群状态:集群的状态可以是健康的(Green)、部分健康的(Yellow)或者不健康的(Red),根据集群中分片的分布和副本的状态来判断。
- 动态扩展:集群可以根据需要动态扩展,可以增加节点、增加分片副本或者增加集群中的分片数量。
2.2.2.2.节点
Elasticsearch中的节点(Node)指的是Elasticsearch实例的运行实例,即一个独立的Elasticsearch服务进程。每个节点都是一个独立的工作单元,负责存储数据、参与数据处理(如索引、搜索、聚合等)以及参与集群的协调工作。
节点是集群中的一个单独服务器,它存储数据并参与集群的索引和搜索操作。每个节点都有一个唯一的名称,并且可以承担不同的角色,例如主节点(负责集群管理)或数据节点(存储数据并处理搜索请求)。节点:类似于集群中的一个成员,每个成员都有特定的任务和职责。
通过多个节点(Node),可以组成Elasticsearch高可用集群
节点可以承担多种角色,包括但不限于:
- 主节点(Master Node):负责集群范围内的元数据管理和变更,如索引创建、删除、分片分配等。
- 数据节点(Data Node):存储实际数据和相关的索引文件,参与数据的索引、搜索和恢复过程。
- 协调节点(Coordinating Node):接收客户端请求,将请求路由至适当的节点,并将结果汇总返回给客户端。每个节点都可以充当协调节点,也可以专门设置某些节点仅作为协调节点。
节点可以在物理或虚拟机上单独部署,也可以在同一台机器上运行多个节点(但需注意资源分配)。节点通过HTTP协议进行通信,共同管理集群的状态和数据。在Elasticsearch集群中,多个节点协同工作,共同提供高效、可靠的数据存储和搜索服务。
2.2.2.3.索引、分片和副本
在 Elasticsearch 中,数据存储在索引中。每个索引可以被分为多个分片(shards),每个分片可以有一个或多个副本(replicas)。在 Elasticsearch 中,分片(Shard)和副本(Replica)是两个重要的概念,它们在集群中起着不同的作用。
2.2.2.3.1.分片
分片是索引的一部分,是数据的基本存储单元。分片允许将索引的数据分布存储在多个节点上,从而实现数据的并行处理和存储。每个分片是一个独立的 Lucene 实例,可以单独进行搜索和索引操作。
- 分片是 Elasticsearch 中存储数据的基本单位,每个索引(Index)都被分成多个分片,每个分片是一个独立的 Lucene 索引。
- 分片的数量在索引创建时就确定了,一旦确定就不能修改。默认情况下,每个索引会被分配 5 个主分片(Primary Shard),可以通过配置来修改。
- 分片的主要作用是实现数据的分布和并行处理。通过将索引数据分成多个分片存储在不同的节点上,可以提高搜索和索引操作的并发性和吞吐量。
- 分片:类似于将一本书拆分成多个章节,每个章节可以单独存放和阅读。
2.2.2.3.2.副本
副本是分片的复制品,用于提高数据的可用性和搜索性能。如果某个节点发生故障,副本可以提供数据的冗余存储,确保数据不会丢失。同时,副本还可以分担搜索请求的负载,提高查询性能。
- 副本是分片的拷贝,每个分片可以有多个副本。副本的数量在索引创建时可以指定,也可以后续动态修改。
- 副本的主要作用是提高数据的可用性和容错性。当某个节点上的分片不可用时,集群可以从其它节点上的副本中提供服务,确保数据的完整性和可用性。
- 默认情况下,每个分片会有一个副本,可以通过配置来修改副本的数量。副本的数量可以根据集群的规模、性能需求和容错需求来灵活调整。
- 副本:类似于书的备份副本,确保即使原书丢失,你仍然有备份可用。
2.2.3.分布式操作
Elasticsearch 的分布式架构使得数据存储和查询变得高效和可靠。以下是一些关键操作及其工作方式:
-
1. 数据分发
当向索引中添加文档时,Elasticsearch 会自动将文档分配到不同的分片中。分片存储在不同的节点上,实现数据的分布式存储。这种分发机制确保数据可以并行处理,提高了存储和索引的速度。
-
2. 查询分发
当执行搜索查询时,Elasticsearch 会将查询请求分发到所有包含相关分片的节点上。这些节点并行处理查询,并将结果返回给协调节点,后者汇总所有结果并返回最终的查询结果。这种并行查询机制大大提高了搜索性能。
-
3. 自动故障恢复
如果集群中的某个节点发生故障,Elasticsearch 会自动检测并将分片的副本提升为主分片,确保数据的高可用性。同时,集群会重新分配分片,确保负载均衡和数据冗余。
2.2.4.例子:分片和副本的工作流程
假设你有一个名为 "products" 的索引,包含 5 个主分片和 1 个副本配置(即每个主分片有一个副本)。在一个由 3 个节点组成的集群中,数据的分布和操作如下:
-
数据分布:5 个主分片和 5 个副本分片将分布在 3 个节点上。例如:
- 节点 1:主分片 1、2,副本分片 3、4。
- 节点 2:主分片 3、4,副本分片 1、5。
- 节点 3:主分片 5,副本分片 2。
-
索引操作:当你向 "products" 索引中添加一个新文档,Elasticsearch 会将该文档分配到某个主分片。例如,文档可能会存储在主分片 1 中,并且副本分片 1 会同步更新该文档。
-
查询操作:当你搜索某个关键词,查询请求将分发到所有包含相关分片的节点上。例如,节点 1 和节点 2 将并行处理查询,并返回部分结果给协调节点进行汇总。
-
故障恢复:如果节点 2 发生故障,Elasticsearch 会自动将副本分片 1 和 5 提升为主分片,确保数据的可用性。然后,Elasticsearch 会在节点 1 和节点 3 之间重新分配分片,以恢复数据冗余。
2.3.倒排索引
倒排索引(Inverted Index)是 Elasticsearch 和其他搜索引擎的核心数据结构,用于实现高效的全文搜索。理解倒排索引的工作原理是掌握 Elasticsearch 搜索性能和效率的关键。
2.3.1.什么是倒排索引?
倒排索引是一种用于存储映射词汇到其在文档中位置的数据结构。它与传统的正排索引(正向索引)不同,后者是将文档与其包含的词汇进行映射。倒排索引的结构类似于一本书的索引部分,其中列出了每个重要词汇以及它们在书中出现的页码。
- 正排索引:类似于一本书的内容目录,列出每章内容及其页码。
- 倒排索引:类似于书的索引部分,列出每个关键字及其出现的页码。
Elasticsearch 中的索引实际上就是所谓的倒排索引,它是所有搜索引擎工作的机制。
看看百度百科的定义:倒排索引_百度百科
倒排索引源于实际应用中需要根据属性的值来查找记录。
在我们百度搜索资料的时候,大家是经常看到搜索不仅仅是局限于标题,大多数时候是搜索到内容的对吧?
从上面可以看出,如果让我们自己去设计数据结构,肯定不能按照以往的那种(查询标题)去设计对吧
正常的mysql:
Goods表:ID addTime goodsName goodsDetails、goodsSEO
我们去设计索引是将goodsName去拆分出词,按照商品名称搜索到该条记录值,但是我们将这条记录放到互联网,那么搜索范围是不是就小太多了?我如果想根据goodsSEO、goodsDetails中的关键词搜索,是不是范围就大了很多,那如何设计呢?
有同学肯定说,那就把goodsSEO、goodsDetails中的词也索引了不就得了,一了百了。
对的,搜索引擎就是这么干的,他把标题、内容都给索引了,这么做,就是倒排/倒置索引,正常的数据数据是:key/value形式,按照key索引即可,倒排索引是按照value去索引,当然了,es是将每个字段都给索引了,也就是每个字段都给你整了一套分词、索引,是不是很贴心?很low?😂
将文档内容进行索引,后面的Document代表该条记录的ID值,也就是整条数据,比如找到了Term中butterfly就找到了Document1了。
2.3.2.倒排索引的工作原理
倒排索引的主要工作原理是将文档中的词汇映射到包含这些词汇的文档列表。以下是倒排索引的构建步骤和基本原理:
- 文档分词:首先,将文档中的文本分割成单独的词汇(即分词)。这一步通常使用分词器(Tokenizer)来完成。
- 去除停用词:分词后,通常会去除一些常见但无意义的词汇,如 "the"、"is" 等,这些词汇称为停用词(Stop Words)。
- 建立词汇表:创建一个包含所有唯一词汇的词汇表。
- 建立倒排列表:对于每个词汇,创建一个倒排列表,记录该词汇在哪些文档中出现以及出现的位置。
示例
假设我们有以下三个文档:
- 文档 1:
"Elasticsearch is a search engine"
- 文档 2:
"Elasticsearch uses inverted index"
- 文档 3:
"Inverted index improves search efficiency"
分词和去除停用词后,我们得到以下词汇表和倒排列表:
- 词汇表:
["Elasticsearch", "search", "engine", "uses", "inverted", "index", "improves", "efficiency"]
- 倒排列表:
"Elasticsearch"
:{文档 1, 文档 2}"search"
:{文档 1, 文档 3}"engine"
:{文档 1}"uses"
:{文档 2}"inverted"
:{文档 2, 文档 3}"index"
:{文档 2, 文档 3}"improves"
:{文档 3}"efficiency"
:{文档 3}
通过倒排列表,我们可以快速定位包含特定词汇的文档,从而提高搜索效率。
2.3.3.倒排索引在 Elasticsearch 中的实现
在 Elasticsearch 中,每个索引都使用倒排索引来实现快速的全文搜索。以下是 Elasticsearch 中倒排索引的实现和工作流程:
- 文档索引:当文档被索引时,Elasticsearch 会对文档中的文本字段进行分词和分析,生成一系列词汇。
- 创建倒排索引:Elasticsearch 为每个词汇创建倒排列表,并将这些列表存储在索引中。
- 搜索查询:当用户执行搜索查询时,Elasticsearch 使用倒排索引来快速定位包含查询词汇的文档,并根据相关性对结果进行排序。
2.3.2.1.分词器
Elasticsearch 使用分词器和分析器来处理文档中的文本。分词器将文本分割成词汇,而分析器则包括分词器和一系列过滤器,用于进一步处理词汇(如去除停用词、转换为小写等)。
在创建索引之前,会对文档中的字符串进行分词。ES中字符串有两种类型,keyword和text。
- keyword类型的字符串不会被分词,搜索时全匹配查询
- text类型的字符串会被分词,搜索时是包含查询
不同的分词器对相同字符串分词的结果大有不同,选择不同的分词器对索引的创建有很大的影响
如拆分“中华人民共和国国歌”
-
ik_max_word分词器: 最细粒度拆分,分词结果如下:
- 中华人民共和国
- 中华人民
- 中华
- 华人
- 人民共和国
- 人民
- 人
- 民
- 共和国
- 共和
- 和
- 国国
- 国歌
-
ik_smart分词器: 最粗粒度的拆分,分词结果如下:
- 中华人民共和国
- 国歌
可见,再ES中创建索引,选择合适的分词器是很重要的。
单词-文档矩阵
- | 单词1 | 单词2 | 单词3 | 单词4 |
---|---|---|---|---|
文档1 | √ | √ | ||
文档2 | √ | |||
文档3 | √ | |||
文档4 | √ | √ |
该矩阵是表达单词和文档两者之间包含关系的概念模型。
从横向看,每行代表文档包含了哪些单词,比如文档1包含了单词1和单词3,而不包含其它单词。
从纵向看,每列代表了某个单词存在于哪些文档。比如单词1在文档1和文档4中出现过。
简单来说,索引就是实现“单词-文档矩阵”的具体数据结构,而倒排索引则是实现了这种数据结构的具体方式。
2.3.4.倒排索引的构成
倒排索引由两部分构成:
- 单词词典
- 倒排列表
它的结构如下:
2.3.4.1.单词词典
单词词典的特性:
- 是文档集合中所有单词的集合
- 它是保存索引的最小单位
- 其中记录着指向倒排列表的指针
单词词典的实现:
单词词典有两种数据结构实现:B+树和Hash表(数据结构那篇文章中有详细介绍)
B+树和Mysql索引结构中主键索引数据结构一样,这里就不再介绍了
哈希表的key是单词的hash值,值是单词的链表,因为hash算法会有冲突的情况发生,所以这里的值是一个集合,里面保存着相同hash值得单词以及改词指向倒排列表的指针
2.3.4.2.倒排列表
倒排列表特性:
- 记录出现过某个单词的文档列表
- 同时还记录单词在所有文档中的出现次数和偏移位置
倒排列表元素数据结构:
其中:
- DocID:出现某单词的文档ID
- TF(Term Frequency):单词在该文档中出现的次数
- POS:单词在文档中的位置
举例
有下面单个文档
- | 内容 |
---|---|
文档1 | 百度的年度目标 |
文档2 | AI技术生态部的年度目标 |
文档3 | AI市场的年度目标 |
则他们生成的倒排索引
单词ID | 单词 | 逆向文档频率 | 倒排列表(DocID;TF;<POS>) |
---|---|---|---|
1 | 目标 | 3 | (1;1;<3>),(2;1;<5>),(3;1;<4>) |
2 | 年度 | 3 | (1;1;<2>),(2;1;<4>),(3;1;<3>) |
3 | AI | 2 | (2;1;<1>),(3;1;<1>) |
4 | 技术 | 1 | (2;1;<2>) |
5 | 生态 | 1 | (2;1;<3>) |
6 | 市场 | 1 | (3;1;<2>) |
比如单词“年度”,单词ID为2,在三个文档中出现过,所以逆向文档频率为3,同时倒排索引中的元素也有三个:(1;1;<2>),(2;1;<4>),(3;1;<3>)
。拿第一个元素(1;1;<2>)
进行说明,他表示“年度”再文档ID为1的文档中出现过1次,出现的位置是第二个单词
2.3.6.倒排索引的搜索过程
直到了倒排索引的内部结构之后,就能很好理解倒排索引的搜索过程了,其内部搜索过程如下图所示:
2.3.7.倒排索引的优势
倒排索引相比其他索引结构具有以下优势:
- 高效搜索:倒排索引允许快速定位包含特定词汇的文档,从而实现高效的全文搜索。
- 灵活性:倒排索引适用于各种类型的搜索查询,包括布尔查询、短语查询和范围查询。
- 扩展性:倒排索引可以轻松扩展以处理大规模数据,适用于分布式搜索系统。
2.4.RESTful API 基本操作示例
RESTful API 是一种遵循 REST(Representational State Transfer)架构风格的应用程序接口。它利用 HTTP 协议的各种方法(如 GET、POST、PUT、DELETE 等)进行资源的创建、读取、更新和删除(CRUD 操作)。在 Elasticsearch 中,资源通常是索引、文档和搜索查询等。
2.4.1. 创建索引
在 Elasticsearch 中,索引类似于数据库中的表,用于存储一类相似的文档。可以使用 PUT 请求创建一个新的索引。
PUT /my_index
响应示例:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "my_index"
}
2.4.2. 添加文档
可以使用 POST 请求将文档添加到索引中。文档以 JSON 格式表示。
POST /my_index/_doc/1
{
"title": "Elasticsearch Introduction",
"content": "Elasticsearch is a powerful search engine.",
"author": "John Doe",
"publish_date": "2024-06-23"
}
响应示例:
{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
2.4.3. 查询文档
可以使用 GET 请求查询特定文档或执行搜索查询。以下示例展示了如何查询特定文档和执行全文搜索。
- 查询特定文档:
GET /my_index/_doc/1
响应示例:
{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true,
"_source": {
"title": "Elasticsearch Introduction",
"content": "Elasticsearch is a powerful search engine.",
"author": "John Doe",
"publish_date": "2024-06-23"
}
}
- 执行全文搜索:
GET /my_index/_search
{
"query": {
"match": {
"content": "search engine"
}
}
}
响应示例:
{
"took": 12,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.2876821,
"hits": [
{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_score": 0.2876821,
"_source": {
"title": "Elasticsearch Introduction",
"content": "Elasticsearch is a powerful search engine.",
"author": "John Doe",
"publish_date": "2024-06-23"
}
}
]
}
}
2.4.4. 更新文档
可以使用 POST 请求更新已存在的文档。更新操作会覆盖指定字段的内容。
POST /my_index/_update/1
{
"doc": {
"content": "Elasticsearch is a powerful and flexible search engine."
}
}
响应示例:
{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
2.4.5. 删除文档
可以使用 DELETE 请求删除特定文档。
DELETE /my_index/_doc/1
响应实例:
{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_version": 3,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}