ElasticSearch 原理分析

在这里插入图片描述

ElasticSearch 的应用场景

适用的场景

全文检索:快速而准确的检索大规模文本数据,适用于搜索引擎,电子商务网站等
日志和事件数据分析:处理各种日志和事件数据,很多公司用es来存储,搜索和分析日志
应用性能监控:通过与各种apm工具集成,可以实时追踪,分析和可视化应用程序的性能指标,帮助开发人员发现潜在问题并进行优化

不适用的场景

不支持事物:如果有强一致的业务场景,比如银行交易,ElasticSearch 不是最佳选择
多表关联有限:尽管 es 有 nested join,但要实现类似 mysql join 几乎不可能或者性能非常差
不支持准实时:refresh_interval(默认1s)决定,近实时而非准实时

ElasticSearch 对标 MySQL 基础概念

ElasticSearchMySQL
IndexTable
DocumentRow
FieldColumn
MappingSchema
Query DSLSQL
aggregationsgroup by,avg,sum
cardinality去重 distinct
reindex数据迁移

倒排索引

正排索引用来保存文档id和文档内容之间的映射关系

文档id文档内容
1ElasticSearch 实战
2ElasticSearch 开发
3ElasticSearch 服务器开发

倒排索引用来保存单词到文档id的映射关系

关键词文档id
ElasticSearch1,2,3
实战1
开发2,3
服务器3

使用倒排索引这一个结构,可以通过关键词快速查询内容

ElasticSearch 存储

在这里插入图片描述

ElasticSearch 中的一个索引由一个或多个分片组成,每个分片包含多个 segment(分段),每一个分段都是一个倒排索引。一个分片就是一个 lucene 索引,分片越多搜索越慢

lucene索引会再分割成分段(segment),分段越多搜索越慢,分段不会被修改,分段会持续的被合并。

更新文档,segment 创建之后不能修改,文档更新实际上是创建了一条新的然后删掉旧的。删除也不是真删,而是加上一条删除标记,分段合并的时候才会彻底删除

删除文档,可以通过id删除单个,也可以通过条件批量删除。删除只是标记为删除,搜索的时候还要检查一遍命中的文档是否已经被删除,分段合并的时候才会彻底删除

ElasticSearch 集群

ElasticSearch作为一个分布式搜索引擎,为了保证高性能,会把索引分成几个分片存储在不同的节点上,这些分片叫做主分片
在这里插入图片描述
同时为了保证高可用,对每个分片还会进行备份,叫做副本分片,主分片和对应的副本分片会尽量避免在同一个节点

如下图圆形代表主分片,正方形代表副本分片,主分片P0对应的副本分片为R1,以此类推
在这里插入图片描述
一个 ElasticSearch 集群除了存储数据的节点外还有很多种其他类型的节点

节点类型作用
master集群的管理节点,负责集群的元数据操作,例如创建或删除索引,管理分片分配
coordinating协调节点,接收请求并将它们分发到相关的 data 节点
ingest执行数据转换和预处理操作
data存储索引数据

在这里插入图片描述
集群形成的大概流程如下

初始化配置:通过 cluster.initial_master_nodes 配置主候选节点,discovery.seed_hosts 指定了在节点发现中的种子主机列表,这个参数告诉节点在加入集群时从哪些主机获取集群配置信息
选举主节点:主候选节点发起主节点的选举,超过一半的主候选节点达成一致表示选举成功
提供服务:当所有节点都发现完毕,集群启动完毕就可以对外提供服务

文档写入流程

当数据量较大时,一个索引会设置多个分片,数据会按照如下规则决定数据应该被保存到哪个分片上

shard_num = hash(_routing) % num_primary_shards

_routing的值是文档的_id值,如果允许主分片数量发生改变,就意味着所有的数据需要重新路由,因此 ElasticSearch 禁止在索引建立以后修改主分片的数量。_routing值可以由用户指定

在这里插入图片描述

  1. 客户端向 node1 发送写数据请求,此时 node1 便充当协调节点的角色
  2. 节点 node1 使用文档的 _id 确定文档属于分片0,请求会被转发到 node3,因为分片0的主分片被分配到 node3
  3. node3 在主分片上执行写入操作,如果写入成功,将请求并行转发到 node1 和 node2 的副本分片。一旦所有副本分片都响应写入成功,node3 将向协调节点响应写入成功,协调节点向客户端响应写入成功

在这里插入图片描述

write:一个新文档过来,会存储在 Memory Buffer 和 Transaction Log 中(事物日志,简写为Translog,默认写入磁盘),此时数据还没到段中,是搜不到新文档的
refresh(刷新):Memory Buffer 中的文档写入新的段中,此时文档可以被搜索到。接着清空 Memory Buffer,注意 Translog 没有被清空
flush(冲洗):每隔一段时间将文档写入磁盘
clear:文档写入磁盘后,删除对应的Translog

refresh_interval 的默认值为1秒,所以 ElasticSearch 是一个近实时的系统

段合并:因为 refresh 默认间隔为1s,所以每秒会创建一个新的段,es 会运行一个任务检测当前磁盘中的段,对符合条件的段进行合并操作,提高查询速度,合并过程也是文档删除和更新操作后,旧的文档真正被删除的时候,我们可以手动调用段合并相关的 api 来主动触发合并

文档搜索流程

在这里插入图片描述

索引写入时总要先寻找主分片,搜索则不然,一个搜索既可以使用主分片,也可以使用副本分片。ElasticSearch 中文档的搜索过程分为两个部分(query 和 fetch)

query 阶段

  1. 客户端向 node1 发送查询请求,此时 node1 便充当协调节点的角色,该 node 会创建一个 priority queue,长度为 from + size
  2. node1 根据负载均衡算法将请求分发到每个分片对应 primary shard 或 replica shard,每个 shard 在本地创建一个同样大小的 priority queue,长度为 from + size,用于存储该 shard 执行查询的结果
  3. 每个 shard 将各自 priority queue 中的元素返回给 node1,注意元素只包含文档的 id 和排序值,node1 将合并所有的元素到自己的 priority queue,根据 from 和 size 获取对应的文档 id

fetch 阶段

在完成 query 阶段后,node1已经得到了查询的列表,但是列表中的元素只有文档的 id 和排序值,并无实际的内容值,所以 fetch 阶段就是根据文档 id,取到完整文档对象的过程,当所有的 shard 都返回了结果,node1 将结果返回给客户端

注意事项:使用 from 和 size 进行分页时,每个 shard 都会创建一个 from + size 长度的队列,当 from 值特别大时,会带来极大的资源浪费,因此不要使用深分页

好用的插件

我们可以在Chrome 应用商店安装一下 ElasticSearch Head 这个插件非常好用,有很多实用的功能

比如下图我们可以看到 user 这个索引只有一个主分片,一个副本分片,主分片在 node-1 这个节点,副本分片在 node -2 这个分片

在这里插入图片描述
我们可以很明显的看到这个集群的状态为绿色

颜色含义
green主分片和副本分片都正常工作
yellow主分片都正常工作,至少一个副本分片不能正常工作
red至少一个主分片以及它的全部副本分片都不能正常工作

参考博客

节点类型
[1]https://www.elastic.co/guide/en/elasticsearch/reference/8.11/modules-node.html
写入流程
[2]https://pdai.tech/md/db/nosql-es/elasticsearch-y-th-3.html
[3]https://elasticsearch.cn/article/13533
倒排索引
[4]https://www.cnblogs.com/wupeixuan/p/12405554.html

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java识堂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值