Elasticsearch 系列之一 —— 初识

本文涉及的产品
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: Elasticsearch 故名思议,Elastic Search 一个分布式搜索中间件。据说是创始人给妻子开发搜索食谱的应用时,顺手做的中间件。果然,爱情的力量是伟大的,否则也不会有至今广受使用的 Elasticsearch 了。​ 分布式、高性能、近实时是 Elasticsearch 的特点。它可以对几乎所有类型的数据(基本值类型、地理空间、IP 等)进行搜索,这依赖于针对不同的类型建立合适的索引结构,后面的系列我们将详细分析索引部分,本次我们分析 Elasticsearch 的系统概念与读写流程。

集群 Cluster

作为一个分布式系统,肯定是需要由多个 ES 实例节点组成集群的。集群需要被管理,ES 中通过 master 来管理集群。集群为了保障高可用,避免单点故障,master 是经过选举选出来的。ES 中,并不是所有的节点都能作为 master 的候选者。

ES 中,一个实例节点也是可以自成集群的

如下图,是一个 常见的ES 集群架构图:

image.png

节点 Node

单个 ES 实例,既称为一个节点。ES 中节点可以有以下一个或多个角色:

候选主节点-Master Eligible Node

用来选主,只有候选主节点才有选举权和被选举权,其它节点不参与选主

选举出的主节点负责创建索引、删除索引、跟踪哪些节点是群集的一部分,并决定哪些分片分配给相关的节点、追踪集群中节点的状态等,稳定的主节点对集群的健康是非常重要的。

通常,为了稳定性,最好使用低配置机器创建独立的候选主节点,且不小于3个。

数据节点-Date Node

负责数据的存储和相关的操作,例如对数据进行增、删、改、查和聚合等操作,所以数据节点(Data 节点)对机器配置要求比较高,对 CPU、内存和 I/O 的消耗很大。

数据节点是集群中压力很大的节点,最好将数据节点和主节点分开,以免影响主节点稳定性,导致脑裂,造成索引、数据不一致等。

1、使用 SSD ,提升磁盘读写能力

2、除了 JVM heap 本身使用的内存外,预留一定的内存给文件缓存,能加快文件访问,避免每次都要访问磁盘

3、禁用 swap 机制

协调节点-Coordinating Node

一般来说,每个节点都可承担协调节点的角色。通常,哪个节点接收客户端请求,就是本次请求的协调节点。协调节点用来处理客户端请求,进行请求分发,结果合并,并返回给客户端。

协调节点的压力介于主节点和数据节点之间,不需要很高的 io 能力。将协调节点独立,有助于降低数据节点的压力,避免互相影响。

ES 集群除了可以有以上常见节点角色外,还有:Ingest node、Remote-eligible node、Machine learning node、Transform node ,感兴趣的可以取官网了解,本文就不一一介绍了。

分片 Shard

一个 data 节点可包含多个 shard 。一个 shard 就是一个 Lucene 实例,索引由一系列 shard 组成。ES 之所以称作分布式搜索,既是可以将数据分散在多个 shard 上,提供更高的性能。

因为写入时,需要通过路由,确定写在哪一个 shard 上,所以需要在索引创建时,确定好 shard 数,一旦设置后将不可变。

副本分片 Replica Shard

一个主 shard 可以有0个或多个副本 shard。默认每个主 shard 都有一个副本 shard,副本 shard 永远不会和主 shard 在同一节点上。主要作用:

1、故障转移:当主 shard 出现故障时,可以将副本 shard 提升为主 shard。

2、提高性能:get、search 请求可以交给主 shard 或副本 shard 处理。

Lucene

Lucene 是一个全文检索库,ES 基于 lucene 来建立。一个 lucene 索引里有很多个 segemnt,每个 segment 都是一个索引结构。在搜索时,会搜索所有的 segment。segment 内部会构建倒排索引,用来检索。

segment 不可变,所以:

1、当文档删除时:lucene 将文档额外标记为删除

2、当更新时:先删除,再插入(新的 segmeng )

写入

当协调节点收到写请求后,通过 routing 找到对应的主 shard,将写请求转发给主 shard,主 shard 写完之后,将写入并发发送给副本 shard,待副本 shard 写入后,返回给主 shard,当所有副本 shard 写完后,主 shard 返回请求给协调节点。

网络异常,图片无法展示
|
image.png

当节点接收到写入请求时,先将数据写入到 index buffer 之中,此时,写入的数据还不能被搜索到,直到数据被 refresh 机制(默认1秒)刷到文件系统缓存,形成不可变的 segment 小索引,此时才能被搜索(近实时搜索)。数据被 refresh 之后,是写入到文件缓存的,并不会立刻持久化到磁盘,而是通过 flush 机制刷到磁盘。

数据写入到 index buffer 中的同时,还会写入到 translog,防止数据丢失。translog 默认5秒会 fsync 到磁盘,所以理论上5秒之内写入的数据,还是有丢失的可能。translog 并不会无限增大,当数据 flush 到磁盘后,translog 就可以进行清理了。

segment flush 时机:

1、5分钟内没有对索引的请求

2、translog 到达一定大小,默认 512m

3、调用 flush api

针对整个集群 flush

curl -XPOST "http://127.0.0.1:9200/_flush/synced"

针对单个索引 flush

curl -XPOST "http://127.0.0.1:9200/demo/_flush/synced"

网络异常,图片无法展示
|
网络异常,图片无法展示
|
image.png

每秒生成一个 segment 会导致文件数量很多,同时造成搜索响应变慢,所以 ES 内部会不定期自动对 segment 进行合并,老的 segment 将删除并释放资源。当然也可以在 ES 压力不大时,进行手动强制合并。

curl -X POST "http://127.0.0.1:9200/demo/_forcemerge"

搜索

当搜索请求到达第一个节点时,其将作为协调节点,负责处理请求。处理流程如图:

网络异常,图片无法展示
|
image.png

如果是分页搜索:假设客户端请求 from = 50,size = 50;协调节点发送给每个 shard 的请求 from = 0,size = from + size = 100;协调节点收到的数据量为 shard 数 * ( from + size ) ;最后再择出分页数据,fetch 得到要获取的数据返回。

基于以上流程,ES 为了避免深度分页对系统的影响,默认对分页有1万条限制的。那怎么解决呢?

1、修改 index. max_result_window 调大限制,可动态设置

curl -XPUT "http://127.0.0.1:9200/demo/_settings" -H 'Content-Type: application/json' -d'

{

 "index.max_result_window": "1000000"

}'

2、Scroll

第一次查询时带上 scroll 参数代表是 scroll 查询,同时设置 scroll 上下文的过期时间:

curl -XGET "http://127.0.0.1:9200/demo/_search?scroll=10s" -H 'Content-Type: application/json' -d'

{

 "size": 20,

 "query": {

   "match_all": {}

 }

}'

返回 _scroll_id:

{

 "_scroll_id": "i1BOVdVWjJyU...",

 ... //省略

}

后续查询将上次返回的 _scroll_id 作为参数:

curl -XGETY "http://127.0.0.1:9200/_search/scroll" -H 'Content-Type: application/json' -d'

{

   "scroll" : "10s",

   "scroll_id" : "i1BOVdVWjJyU..."

}'

scroll 需要在 ES 服务端持续维持一个快照上下文,持有 segment 。此时 segment 合并仍可继续,但却不能删除老的 segment 释放资源。直到过期或者手动清理:

curl -XDELETE "http://127.0.0.1:9200/_search/scroll" -H 'Content-Type: application/json' -d'

{

   "scroll_id" : "i1BOVdVWjJyU..."

}'

 当遍历大量数据时,可通过 slice scroll 加快速度

3、Search After

curl -XGET "http://127.0.0.1:9200/demo/_search" -H 'Content-Type: application/json' -d'

{

 "from": 0,//from 永远从0开始

 "size": 10,

 "query": {

   "match_all": {}

 },

 "search_after": [ //初次不传,后续使用上次最后元素的排序值作为参数

   674688494483205

 ],

 "sort": [

   {

     "_id": { //稳定排序,建议最后排序字段用 _id

       "order": "desc"

     }

   }

 ]

}'

需要设置排序字段,并且是稳定排序,通常最后排序字段是 _id。记录上页最后元素的排序值,作为下次的查询条件。相比 scroll 是服务端无状态的,不占用 ES 资源。

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
相关文章
|
Java 测试技术 网络安全
PTS报错问题之压测报错如何解决
PTS(Performance Testing Service)是一项面向网站、应用等提供的压力测试服务,用于模拟不同场景下的用户访问,评估系统的性能表现;在进行PTS压测时,可能会出现一些异常或报错,本合集将PTS压测中频繁出现的问题及其解决办法进行汇编,旨在帮助用户更有效地进行性能测试和问题定位。
|
数据安全/隐私保护 虚拟化 Windows
如何在 VM 虚拟机中安装 Windows XP 操作系统保姆级教程(附链接)
如何在 VM 虚拟机中安装 Windows XP 操作系统保姆级教程(附链接)
|
存储
openzfs draid是什么
openzfs draid是什么
2407 0
openzfs draid是什么
|
存储 索引
Elasticsearch分布式架构
【11月更文挑战第2天】
192 1
|
前端开发 Linux API
Avalonia:一个.NET跨平台UI框架
Avalonia:一个.NET跨平台UI框架
701 0
|
NoSQL 算法 Java
使用 Spring Boot 实现限流功能:从理论到实践
【6月更文挑战第18天】在微服务和高并发系统中,限流(Rate Limiting)是一种非常重要的技术手段,用于保护系统免受过载,确保服务的稳定性。限流可以控制请求的速率,防止单个客户端或恶意用户消耗过多的资源,从而影响其他用户。
1440 5
|
存储 负载均衡 NoSQL
【Redis系列笔记】Redis集群
集群是一种在多个计算机或服务器之间分配和管理任务的方式。它们被广泛应用于大型计算任务、数据处理、网络服务和高性能计算等领域。在Redis中,主要有以下三种集群,分别是主从集群,哨兵集群,分片集群。
476 18
|
存储 SQL 运维
亿级异构任务调度框架设计与实践
阿里云日志服务作为云原生可观测与分析平台。提供了一站式的数据采集、加工、查询分析、可视化、告警、消费与投递等功能。全面提升用户的研发、运维、运营、安全场景的数字化能力。 日志服务平台作为可观测性平台提供了数据导入、数据加工、聚集加工、告警、智能巡检、导出等功能,这些功能在日志服务被称为任务,并且具有大规模的应用,接下来主要介绍下这些任务的调度框架的设计与实践。
1953 0
亿级异构任务调度框架设计与实践
|
SQL 分布式计算 数据处理
Spark的生态系统概览:Spark SQL、Spark Streaming
Spark的生态系统概览:Spark SQL、Spark Streaming
事务 @Transactional 的 Propagation.REQUIRES_NEW
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/catoop/article/details/53482960 小经验: 同一个业务类里面 , 即使声明为 Propagation.REQUIRES_NEW也不会新启一个事务。
1553 0