Githubhttps://github.com/HealerJean

博客:http://blog.healerjean.com

一、Elasticsearch 应用

1、和 Mysql 的对比

⬤ 对安全性要求较高的写操作,使用 mysql 实现

⬤ 对查询性能要求较高的搜索需求,使用 elasticsearch 实现

⬤ 两者再基于某种方式,实现数据的同步,保证一致性

MySQL Elasticsearch 说明
Table Index 索引( index),就是文档的集合,类似数据库的表(table)
Row Document 文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是 JSON格式
Column Field 字段(Field),就是 JSON 文档中的字段,类似数据库中的列(Column
Schema Mapping Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema
SQL DSL DSLelasticsearch 提供的 JSON 风格的请求语句,用来操作elasticsearch,实现CRUD
  客户端工具 复制方式
mysql navicat, SQLyog, MySQL Workbench 主从
ES elasticsearch-head, Kibana, Elasticsearch-sql, Elasticsearch-HQ 对等

es 在5.x以后,没有了string 类型,被拆分为关键词搜索 keyword 和全文搜索text

  keyword text
自动分词
支持聚合

2、初识elasticsearch

1)Lucene

elasticsearch 底层是基于 lucene 来实现的。Lucene是一个 Java 语言的搜索引擎类库,是 Apache 公司的顶级项目

Lucene 优势:易扩展,高性能(基于倒排索引)

Lucene 缺点:只限于 java 语言开发,学习成本高,不支持水平扩展

2)elasticsearch

基于 Lucene 开发,支持分布式,可水平扩展,提供 Restful接口,可被任何语言调用

3)倒排索引

倒排索引的概念是基于 MySQL这样的正向索引而言的。

a、 正向索引

设置了索引的话挺快的,但要是模糊查询则就很慢!

如果是根据 id 查询,那么直接走索引,查询速度非常快。但如果是基于 title 做模糊查询,只能是逐行扫描数据,流程如下:

1)用户搜索数据,条件是title符合"%手机%"

2)逐行获取数据,比如id为1的数据

3)判断数据中的title是否符合用户搜索条件

4)如果符合则放入结果集,不符合则丢弃。回到步骤1

逐行扫描,也就是全表扫描,随着数据量增加,其查询效率也会越来越低。当数据量达到数百万时,就是一场灾难

image-20240426144036996

b、倒排索引

虽然要先查询倒排索引,再查询正向索引,但是无论是词条、还是文档id都建立了索引,查询速度非常快!无需全表扫描。

1、倒排索引中有两个非常重要的概念:

⬤ 文档(Document):用来搜索的数据,其中的每一条数据就是一个文档。例如一个网页、一个商品信息

⬤ 词条(Term):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条。例如:我是中国人,就可以分为:我、是、中国人、中国、国人这样的几个词条

2、创建倒排索引是对正向索引的一种特殊处理,流程如下

⬤ 将每一个文档的数据利用算法分词,得到一个个词条

⬤ 创建表,每行数据包括词条、词条所在文档id、位置等信息

⬤ 因为词条唯一性,可以给词条创建索引,例如 hash表结构索引

image-20240426144333121

倒排索引的搜索流程如下(以搜索”华为手机”为例):

1)用户输入条件"华为手机"进行搜索。

2)对用户输入内容分词,得到词条:华为手机

3)拿着词条在倒排索引中查找,可以得到包含词条的文档id:1、2、3。

4)拿着文档 id 到正向索引中查找具体文档。

如图:

image-20240426144427948

3)正向和倒排对比

正向索引是最传统的,根据 id 索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程

⬤ 而倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的 id,然后根据 id 获取文档。是根据词条找文档的过程

  优点 缺点
正向索引 可以给多个字段创建索引 根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。
  根据索引字段搜索、排序速度非常快  
     
倒排索引 根据词条搜索、模糊搜索时,速度非常快 只能给词条创建索引,而不是字段
    无法根据字段做排序

2、场景

1)内容搜索

您经营一家网上商店,允许您的客户搜索您销售的产品。在 这种情况下,您可以使用 Elasticsearch 存储整个产品目录 和库存,并为他们提供搜索和搜索词自动补全功能。

3)日志查询

您希望收集日志或事务数据,并且希望分析这些数据以发现 其中的趋势、统计特性、摘要或反常现象。在这种情况下, 您可以使用Logstash ( Elastic Stack的一个组件)来收集、聚合和分析您的数据,然后使用 Logstash 将经过处理的数据导入Elasticsearch。一旦数据进入 Elasticsearch ,您 就可以通过搜索和聚合来挖掘您感兴趣的任何信息。

3)内容匹配

您运行一个价格警报平台,它允许为对价格敏感的客户制定 一个规则

例如,“我有兴趣购买特定的电子小工具,如果 小工具的价格在下个月内低于任何供应商的某个价格,我希 望得到通知”。在这种情况下,您可以获取供应商价格,将其推送到 Elasticsearch,并使用其反向搜索(过滤,也就 是范围查询) 功能根据客户查询匹配价格变动,最终在找到 匹配项后将警报推送给客户。

4)大量数据存储

您有分析或商业智能需求,并且希望可以对大量数据(数百 万或数十亿条记录)进行快速研究、分析、可视化并提出特定的问题。在这种情况下,您可以使用 Elasticsearch 来存 储数据,然后使用 Kibana( Elastic Stack 的一部分)来构 建自定义仪表盘(dashboard),以可视化对您重要的数据 维度。此外,还可以使用 Elasticsearch 聚合功能对数据执 行复杂的查询。

二、基本概念

1、近实时

Elasticsearch 是一个近实时( Near Real TimeNRT )的数据 搜索和分析平台。这意味着从索引文档到可搜索文档都会有一段微小 的延迟(通常是1s以内)。

2、集群

集群( cluster )是一个或多个节点( node )的集合,这些节点将共同拥有完整的数据,并跨节点提供联合索引、搜索和分析功能。 集群由唯一的名称标识 ( elasticsearch.yml 配置文件中对应参数 cluster.name),集群的名称是 elasticsearch.yml 配置文件中最重要的一个配置参数,默认名称为 Elasticsearch,节点只能通过集群名称加入集群。

注意:

1、请确保不要在不同的环境中使用相同的集群名称,否则可能会导 致节点加入错误的集群。例如,可以使用 loggingdevloggingstageloggingprod 来区分开发、预发布和生产环境的集群。

3、节点

节点( node )是一个 Elasticsearch 的运行实例,也就是一进程( process),多个节点组成集群,节点存储数据,并参与集群的 索引、搜索和分析功能。

⬤ 与集群一样,节点由一个名称标识,默认情况下,该名称是在启动时分配给节点的随机通用唯一标识符 (UUID)。如果不希望使用默认值,可以定义所需的任何节点名 称。此名称对于集群管理很重要,因为在实际应用中需要确定网络中 的哪些服务器对应于 Elasticsearch 集群中的哪些节点。

1)加入集群

可以通过集群名称将节点配置为加入特定集群。

1、默认情况下,每 个节点都被设置为加入一个名为 Elasticsearch的集群,这意味着, 如果在网络上启动了多个节点,并且假设它们可以彼此发现,那么它们都将自动形成并加入一个名为 Elasticsearch的集群。

2、在单个集群中,可以有任意多个节点。此外,如果当前网络上没有其他 Elasticsearch 节点在运行,则默认情况下,启动单个节点将形成一个名为Elasticsearch 的新单节点集群。

2)节点实质是一个进程

上面提到了节点实质是一个进程,因此服务器和节点可以 是一对多的关系。还有一点需谨记,无论是开发环境、测试环境还是生产环境请配置有意义的节点名称

4、索引

索引( index ) 是具有某种相似特性的文档集合。例如,可以有 存储客户数据的索引,存储产品目录的索引,以及存储订单数据的索 引。索引由一个名称(必须全部是小写)标识,当对其中的文档执行索引、搜索、更新和删除操作时,该名称指向这个特定的索引。 在单个集群中,可以定义任意多个索引。

5、文档

文档 ( document )是可以被索引的基本信息单元。例如,可以 为单个客户创建一个文档,为单个产品创建另一个文档,以及为单个 订单创建另一个文档。文档以 JSON 表示, JSON是 一种普遍存在的 Internet 数据交换格式。在单个索引中,理论上可以存储任意多的文档。

6、分片和副本

索引可能会存储大量数据,这些数据可能会超出单个节点的硬件 限制。例如,占用 1TB 磁盘空间的10 亿个文档的单个索引可能超出单个节点的磁盘容量,或者速度太慢,无法满足搜索请求的性能要求。

1)分片-解决单个节点容量问题

为了解决这个问题,Elasticsearch 提供了将索引水平切分为多段 ( 称为分片,shard )的能力。创建索引时,只需定义所需的分片 数量。每个分片本身就是一个具有完全功能的独立 “索引”,可以分布在集群中的任何节点上。

1、分片可以水平拆分数据,实现大数据存储和分析

2、可以跨分片 ( 可能在多个节点上 ) 进行分发和并行操作,从 而提高性能和吞吐量。

如何分配分片以及如何将其文档聚合回搜索请求的机制完全由 Elasticsearch 管理,并且对用户是透明的

2)副本-防止分片活节点宕机

在随时可能发生故障的网络或云环境中,如果某个分片或节点以 某种方式脱机或因何种原因丢失,则强烈建议用户使用故障转移机制。为此,Elasticsearch 提出了将索引分片复制一个或多个拷贝, 称为副本( replica)。

1、副本在分片或节点发生故障时提供高可用性。因此,需要注 意的是,副本永远不会分配到复制它的原始主分片所在的节 点上。也就是分片和对应的副本不可在同一节点上。这很容易理解,如果副本和分片在同一节点上,当机器发生故障时 会同时丢失,起不到容错的作用

2、通过副本机制,可以提高搜索性能和水平扩展吞吐量,因为 可以在所有副本上并行执行搜索。

总之,每个索引可以分割成多个分片。每个分片可以有零个或多个副本

3)创建分片和副本

可以在创建索引时为每个索引定义分片和副本的数量。创建索引后,

1、可以随时动态更改副本的数量。

2、 分片的数量理论上不可变更, 唯一的办法重建索引,重新定义分片数量。但还是可以使用 shrinksplit API更改索引的分片数量,但这不是通常的做法,预先评估 准确的分片数量才是最佳方法

默认情况下,Elasticsearch 中的每个索引都分配一个主分片和一个副本,这意味着如果集群中至少有两个节点,则索引将有一个主分片和另一个副本分片(一个完整副本),每个索引总共有两个分片

本质上分片和副本都是一个完整的 Lucenes 索引,存储的数 据也是完全相同的,都可以称为分片

假设一个索引定义了 3 个分片、2 个副本,那么总共就是 9 个 分片,其中 3 个是主分片,每个主分片有 2 个副本。主分片就 是建立索引时首先建立的分片,或者说当主分片失效时会重 新选出一个副本作为主分片。

1、当索引时,数据会首先到达主分片,然后再把请求分发到其 他副本。

2、当搜索时,主分片和副本都可以接受请求、搜索和分析数据,二者没有区别。

三、安装

1、ES

官网:https://www.elastic.co/cn/downloads/elasticsearch

1、运行:

./bin/elasticsearch

2、启动成功:

http://localhost:9200/
{
    "name": "MacPro.mshome.net",
    "cluster_name": "elasticsearch",
    "cluster_uuid": "wm9k6z1cSBGBoV92K7tAFQ",
    "version": {
        "number": "8.2.2",
        "build_flavor": "default",
        "build_type": "tar",
        "build_hash": "9876968ef3c745186b94fdabd4483e01499224ef",
        "build_date": "2022-05-25T15:47:06.259735307Z",
        "build_snapshot": false,
        "lucene_version": "9.1.0",
        "minimum_wire_compatibility_version": "7.17.0",
        "minimum_index_compatibility_version": "7.0.0"
    },
    "tagline": "You Know, for Search"
}

3、目录

目录 配置文件 描述
bin   脚本文件,包括启动elasticsearch,安装插件,统计数据等。
config elasticsearch.yml 集群配置文件,user,role based 相关配置等。
JDK   java 运行环境
data path.data 数据文件
lib   java 类库
logs path.log 日志文件
modules   包含所有es模块
plugins   包含所有以安装的插件

2、 kibana

官方:https://www.elastic.co/cn/downloads/kibana

1、修改配置 kibana.yml

server.port: 5601


elasticsearch.hosts: ["http://localhost:9200"]

2、启动

注意要启动 elasticsearch

./kibana
http://localhost:5601

四、原理

Elasticsearch 中的每个索引都分为多个分片,每个分片可以有 多个副本,这些副本称为复制组

注意:在添加或删除文档时必须保持同步。如果不这样做,将导致从一个副本中读取的数据与从另一个副本 中读取的数据表现出截然不同的结果。保持主分片和副本间

复制模型:两两副 本间的数据同步并提供读取服务的过程,我们称之为数据复制模型。

下图展示了复制组的具体含义,此复制组有三个分片,加粗的是主分片,其他两个是副本,这三个分片的数据必须保持一致

image-20220601174517312

1、主备模型

Elasticsearch 的数据复制模型是基于主备 ( primary - backup ) 模型的,这个模型在微软研究中心的 Pacifica 论文中有很好的描述。 该模型基于复制组中作为主分片的单个数据分片。意思是,假设一个 索引有3个分片、2个副本,那么每个子索引共有3个分片,其中一个 是主分片,两个是副本,

为了便于描述主分片,我们称主分片为 primary,称副本为 replicaprimary 用作所有索引操作的主入口点,它负责验证它们并确保它们是正确的。一旦索引操作被 primary 接受,primary 还负责将该操作复制到其他 replica (分发请求到其他 replica)。另外约定,集群中有若干个节点,其中只有一个是活跃的 主节点,它负载管理集群,我们把它称为 master

2、基本写模型

Elasticsearch 中的每个索引操作首先使用路由 (通常基于文档 ID )解析到一个复制组。一旦确定了复制组,该操作将在内部转发到 该组的当前 primary

primary 负责验证操作并将其转发到其他 replica。由于 replica 可以离线,因此不需要 primary复制到所有 replica

⬤ 相反,Elasticsearch 维护一个应该完成接收操作的 replica 列表,此列表称为同步副本组,由主节点维护。顾名思义,这些是一 组“好”的分片拷贝,保证已经处理了所有的索引和删除操作,这些 操作已经被用户确认。primary 负责维护这个不变量,因此必须将所有操作复制到这个同步副本组中的每个 replica

1)primary 写流程

1、验证传入操作,如果结构无效则拒绝该操作。例如,向一个数 字字段传输一个对象类型。

2、在本地执行操作,即索引或删除相关文档。这还将验证字段的内容,并在需要时拒绝。例如,关键字值对于 Lucene中的索引而言太长了。

3、将操作转发到当前同步副本组中的每个 replica,如果有多个 replica,这是并行完成的。

4、一旦所有 replica 都成功地执行了操作并对 primary 作出了响 应,primary 就确认完成了请求并返回给用户。

2)写流程错误处理

索引数据期间可能会有多种异常情况发生,磁盘可能损坏,节点可能彼此断开,或者某些配置错误可能导致操作在 replica 失败,尽管 在 primary 上成功。这种情况虽然不常见,但 primary 必须对它们作 出反应。

1、故障转移:如果 primary 本身发生故障,primary 所在的节点将向 master 节点发送相关的消息。索引操作将等待(默认情况下最多1分钟) master 将其中一个 replica 提升为新的 primary。然后该操作将被转发 到新的 primary 进行处理。同时,master 还监视节点的运行状况,并可能决定主动降级 primaryreplica,当包含 primary 的节点由于网络问题与集群隔离时,通常会发生这种情况。

2、副本摘除:一旦在 primary上成功执行了操作,primary 就必须处理在 ` replica上执行时潜在的故障。这可能是由于 replica上的实际故障或 网络问题导致操作无法到达 replica (或阻止replica响应)。所有这 些问题会造成相同的最终结果: 作为同步副本组的一部分的 replica会 错过即将被确认的操作。为了避免违反不变量,primarymaster 发 送一条消息,请求从同步副本组中删除有问题的replica。只有在 master 确认清除 replica 后,primary 才会确认该操作。同时, master` 还将指示另一个节点开始构建新的副本,以便将系统恢复到健 康状态。

3、主节点下线: 在将操作转发到其他 replica 时,primary 将使用 replica 来验证它是否仍然是活动的 primary。如果由于网络分区(或GC时间过长)而 隔离了primary,则在知道到它已降级之前,它可能会继续处理传入的索引操作。来自过时 primary 的操作将被 replica拒绝,当 primary 接收到来自拒绝其请求的 replica的响应时,它将到达 master并知道 它已经被替换,然后将操作路由到新的 primary

3、基本读模型

Elasticsearch 中的读取可以是非常轻量的按 ID 查找,也可以是 一个具有复杂聚合的繁重搜索请求,这些聚合需要非常大的 CPU 能 力。主备 (primary - backup )模型的一个优点是它保持所有的分片 (primaryreplica )是等同的。因此,单个同步拷贝(称之为相关分片组)就足以满足读取请求。

1)读流程

当节点接收到读取请求时,该节点负责将其转发到保存相关分片的节点整理响应,并向客户机返回结果。该节点被称为该请求的协调 节点。基本流程如下:

1、将读取请求解析到相关分片组。注意,由于大多数搜索将被发送到一个或多个索引,所以它们通常需要从多个分片中读取,每个分片表示数据的不同子集。

2、从同步副本组中选择一个相关 shard 的活动分片。这可以是 primary,也可以是 replica。默认情况下,Elasticsearch 只需在分片之间循环搜索。

3、向所选分片发送读取请求。

4、将结果整合。请注意,在按 ID 查找的情况下,只有一个分片是 相关的,可以跳过此步骤。

2)读流程错误处理

当一个分片未能响应读取请求时,协调节点将请求发送到同步副 本组中的另一个分片。重复失败可能导致没有可用的分片。为了确保快速响应,如果一个或多个分片失败,以下 API 将以部分结果响应:

⬤ Search API

⬤ Multi Search

⬤ Bulk

⬤ Multi Get

包含部分结果的响应仍然提供200 OK HTTP状态代码。相关分 片的失败信息记录在响应头部字段里。

ContactAuthor