ES_之_基本概念
Github:https://github.com/HealerJean
一、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 |
DSL 是 elasticsearch 提供的 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
逐行扫描,也就是全表扫描,随着数据量增加,其查询效率也会越来越低。当数据量达到数百万时,就是一场灾难

b、倒排索引
虽然要先查询倒排索引,再查询正向索引,但是无论是词条、还是文档id都建立了索引,查询速度非常快!无需全表扫描。
1、倒排索引中有两个非常重要的概念:
⬤ 文档(Document):用来搜索的数据,其中的每一条数据就是一个文档。例如一个网页、一个商品信息
⬤ 词条(Term):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条。例如:我是中国人,就可以分为:我、是、中国人、中国、国人这样的几个词条
2、创建倒排索引是对正向索引的一种特殊处理,流程如下:
⬤ 将每一个文档的数据利用算法分词,得到一个个词条
⬤ 创建表,每行数据包括词条、词条所在文档id、位置等信息
⬤ 因为词条唯一性,可以给词条创建索引,例如 hash表结构索引

倒排索引的搜索流程如下(以搜索”华为手机”为例):
1)用户输入条件"华为手机"进行搜索。
2)对用户输入内容分词,得到词条:华为、手机。
3)拿着词条在倒排索引中查找,可以得到包含词条的文档id:1、2、3。
4)拿着文档 id 到正向索引中查找具体文档。
如图:

3)正向和倒排对比
⬤ 正向索引是最传统的,根据
id索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程。⬤ 而倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的
id,然后根据id获取文档。是根据词条找文档的过程。
| 优点 | 缺点 | |
|---|---|---|
| 正向索引 | 可以给多个字段创建索引 | 根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。 |
| 根据索引字段搜索、排序速度非常快 | ||
| 倒排索引 | 根据词条搜索、模糊搜索时,速度非常快 | 只能给词条创建索引,而不是字段 |
| 无法根据字段做排序 |
2、场景
1)内容搜索
您经营一家网上商店,允许您的客户搜索您销售的产品。在 这种情况下,您可以使用
Elasticsearch存储整个产品目录 和库存,并为他们提供搜索和搜索词自动补全功能。
3)日志查询
您希望收集日志或事务数据,并且希望分析这些数据以发现 其中的趋势、统计特性、摘要或反常现象。在这种情况下, 您可以使用
Logstash(Elastic Stack的一个组件)来收集、聚合和分析您的数据,然后使用Logstash将经过处理的数据导入Elasticsearch。一旦数据进入Elasticsearch,您 就可以通过搜索和聚合来挖掘您感兴趣的任何信息。
3)内容匹配
您运行一个价格警报平台,它允许为对价格敏感的客户制定 一个规则
例如,“我有兴趣购买特定的电子小工具,如果 小工具的价格在下个月内低于任何供应商的某个价格,我希 望得到通知”。在这种情况下,您可以获取供应商价格,将其推送到
Elasticsearch,并使用其反向搜索(过滤,也就 是范围查询) 功能根据客户查询匹配价格变动,最终在找到 匹配项后将警报推送给客户。
4)大量数据存储
您有分析或商业智能需求,并且希望可以对大量数据(数百 万或数十亿条记录)进行快速研究、分析、可视化并提出特定的问题。在这种情况下,您可以使用
Elasticsearch来存 储数据,然后使用Kibana(ElasticStack的一部分)来构 建自定义仪表盘(dashboard),以可视化对您重要的数据 维度。此外,还可以使用Elasticsearch聚合功能对数据执 行复杂的查询。
二、基本概念
1、近实时
Elasticsearch是一个近实时(NearRealTime,NRT)的数据 搜索和分析平台。这意味着从索引文档到可搜索文档都会有一段微小 的延迟(通常是1s以内)。
2、集群
集群(
cluster)是一个或多个节点(node)的集合,这些节点将共同拥有完整的数据,并跨节点提供联合索引、搜索和分析功能。 集群由唯一的名称标识 (elasticsearch.yml配置文件中对应参数cluster.name),集群的名称是elasticsearch.yml配置文件中最重要的一个配置参数,默认名称为Elasticsearch,节点只能通过集群名称加入集群。
注意:
1、请确保不要在不同的环境中使用相同的集群名称,否则可能会导 致节点加入错误的集群。例如,可以使用 loggingdev、loggingstage 和 loggingprod 来区分开发、预发布和生产环境的集群。
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、 分片的数量理论上不可变更, 唯一的办法重建索引,重新定义分片数量。但还是可以使用
shrink和splitAPI更改索引的分片数量,但这不是通常的做法,预先评估 准确的分片数量才是最佳方法。
默认情况下,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中的每个索引都分为多个分片,每个分片可以有 多个副本,这些副本称为复制组注意:在添加或删除文档时必须保持同步。如果不这样做,将导致从一个副本中读取的数据与从另一个副本 中读取的数据表现出截然不同的结果。保持主分片和副本间
复制模型:两两副 本间的数据同步并提供读取服务的过程,我们称之为数据复制模型。
下图展示了复制组的具体含义,此复制组有三个分片,加粗的是主分片,其他两个是副本,这三个分片的数据必须保持一致

1、主备模型
Elasticsearch的数据复制模型是基于主备 (primary-backup) 模型的,这个模型在微软研究中心的Pacifica论文中有很好的描述。 该模型基于复制组中作为主分片的单个数据分片。意思是,假设一个 索引有3个分片、2个副本,那么每个子索引共有3个分片,其中一个 是主分片,两个是副本,为了便于描述主分片,我们称主分片为
primary,称副本为replica。primary用作所有索引操作的主入口点,它负责验证它们并确保它们是正确的。一旦索引操作被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 还监视节点的运行状况,并可能决定主动降级 primary 为 replica,当包含 primary 的节点由于网络问题与集群隔离时,通常会发生这种情况。
2、副本摘除:一旦在 primary上成功执行了操作,primary 就必须处理在 ` replica上执行时潜在的故障。这可能是由于 replica上的实际故障或 网络问题导致操作无法到达 replica (或阻止replica响应)。所有这 些问题会造成相同的最终结果: 作为同步副本组的一部分的 replica会 错过即将被确认的操作。为了避免违反不变量,primary 向 master 发 送一条消息,请求从同步副本组中删除有问题的replica。只有在 master 确认清除 replica 后,primary 才会确认该操作。同时, master` 还将指示另一个节点开始构建新的副本,以便将系统恢复到健 康状态。
3、主节点下线: 在将操作转发到其他 replica 时,primary 将使用 replica 来验证它是否仍然是活动的 primary。如果由于网络分区(或GC时间过长)而 隔离了primary,则在知道到它已降级之前,它可能会继续处理传入的索引操作。来自过时 primary 的操作将被 replica拒绝,当 primary 接收到来自拒绝其请求的 replica的响应时,它将到达 master并知道 它已经被替换,然后将操作路由到新的 primary。
3、基本读模型
Elasticsearch中的读取可以是非常轻量的按ID查找,也可以是 一个具有复杂聚合的繁重搜索请求,这些聚合需要非常大的CPU能 力。主备 (primary-backup)模型的一个优点是它保持所有的分片 (primary和replica)是等同的。因此,单个同步拷贝(称之为相关分片组)就足以满足读取请求。
1)读流程
当节点接收到读取请求时,该节点负责将其转发到保存相关分片的节点整理响应,并向客户机返回结果。该节点被称为该请求的协调 节点。基本流程如下:
1、将读取请求解析到相关分片组。注意,由于大多数搜索将被发送到一个或多个索引,所以它们通常需要从多个分片中读取,每个分片表示数据的不同子集。
2、从同步副本组中选择一个相关 shard 的活动分片。这可以是 primary,也可以是 replica。默认情况下,Elasticsearch 只需在分片之间循环搜索。
3、向所选分片发送读取请求。
4、将结果整合。请注意,在按 ID 查找的情况下,只有一个分片是 相关的,可以跳过此步骤。
2)读流程错误处理
当一个分片未能响应读取请求时,协调节点将请求发送到同步副 本组中的另一个分片。重复失败可能导致没有可用的分片。为了确保快速响应,如果一个或多个分片失败,以下
API将以部分结果响应:
⬤ Search API
⬤ Multi Search
⬤ Bulk
⬤ Multi Get
包含部分结果的响应仍然提供200 OK HTTP状态代码。相关分 片的失败信息记录在响应头部字段里。


