ElasticSearch 基本概念

在这里插入图片描述

ElasticSearch 基本概念

ElasticSearch 中有几个比较核心的概念,为了方便你理解,我将其与数据库中的概念进行映射,如下图所示:

在这里插入图片描述
注意:在老版本的 ElasticSearch 中,Index 和 Document 之间还有个 Type 的概念,每个 Index 下可以建立多个 Type,Document 存储时需要指定 Index 和 Type。从 ES 6.0 版本开始单个 Index 中只能有一个 Type,ES 7.0 版本以后将不建议使用 Type,ES 8.0 以后完全不支持 Type。

Index 是具有某些类似特征的 Document 的集合,Index 与 Document 之间的关系就类似于数据库中 Table 与 Row 之间的关系。在 Index 中可以存储任意数量的 Document。在后续介绍的示例中可以看到,对 Document 的添加、删除、更新、搜索等操作,都需要明确的指定 Index 名称。

最后,还需要了解 ElasticSearch 中一个叫作 Index Template(模板)的概念。Index Template 一般会包含 settingsmappingsindex_patternsorderaliases 几部分:

index_patterns 负责匹配 Index 名称,Index Template 只会应用到名称与之匹配的 Index 上,而且 ElasticSearch 只会在 Index 创建的时候应用匹配的 Index Template,后续修改 Index Template 时不会影响已有的 Index。通过 index_patterns 匹配可以让多个 Index 重用一个 Index Template。

settings 主要用于设置 Index 中的一些相关配置信息,如分片数、副本数、refresh 间隔等信息(后面会介绍分片数和副本数的概念);
mappings 主要是一些说明信息,类似于定义该 Index 的 schema 信息,例如,指定每个 Field 字段的数据类型;

order 主要作用于在多个 Index Template 同时匹配到一个 Index 的情况,如果此时这些Index Template 中的配置出现不一致,则以 order 的最大值为准,order 默认值为 0。另外,创建 Index 的命令中如果自带了 settings 或 mappings 配置,则其优先级最高;

aliases 则是为匹配的 Index 创建别名。我们可以通过请求 http://localhost:9200/_alias/*获取所有别名与 Index 之间的对应关系。

下面是 SkyWalking 使用的 segment 模板,它会匹配所有 segment-* 索引,segment-yyyyMMdd 索引是用来存储 Trace 数据的:

{
    "segment": {
        "order": 0,
        "index_patterns": [
            "segment-*"
        ],
        "settings": {
            "index": {
                "refresh_interval": "3s",
                "number_of_shards": "2",
                "number_of_replicas": "0"
                // 省略 analysis字段设置
            }
        },
        "mappings": {
            "type": {
                "properties": {
                    "segment_id": {
                        "type": "keyword"
                    },
                    "trace_id": {
                        "type": "keyword"
                    },
                    "service_id": {
                        "type": "integer"
                    },
                    // 省略其他字段的设置
                }
            }
        },
        "aliases": { // 为匹配的Index创建别名
            "segment": {}
        }
    }
}

节点角色

一个 ElasticSearch 集群是由一个或多个节点组成,这些节点共同存储了集群中的所有数据,并且 ElasticSearch 提供了跨节点的联合索引和搜索功能。集群名称是一个 ElasticSearch 集群的唯一标识,在请求 ElasticSearch 集群时都需要使用到这个集群名称。在同一个网络环境中,需要保证集群名称不重复,否则集群中的节点可能会加入到错误的集群中。

ElasticSearch 集群是去中心化的,ElasticSearch 节点的相互发现是基于 Pull-Push 版本的 Gossip 算法实现的。Zen Discovery 是 ElasticSearch 默认的发现实现,提供了广播和单播的能力,帮助一个集群内的节点完成快速的相互发现。

ElasticSearch 集群中的节点有多个可选的角色,这些角色都是通过在节点的配置文件中配置的。

Master Eligible Node (候选主节点):可以被选举为 Master 的候选节点;
Master Node (主节点):完成节点发现阶段之后,才会进入主节点选举阶段,为了防止在网络分区的场景下出现脑裂问题,一般采用 quorum 版本的 Bully 算法变体(本课时重点是帮助你快速了解 ElasticSearch 基础知识,不展开该算法的具体原理)。所以,主节点是从候选主节点中选举出来的,主要负责管理 ElasticSearch 集群,通过广播的机制与其他节点维持关系,负责集群中的 DDL 操作(创建/删除索引),管理其他节点上的分片;
Data Node(数据节点):存放数据的节点,负责数据的增删改查;
Coordinating Node(协调节点):每个节点都是一个潜在的协调节点,协调节点最大的作用就是响应客户端的请求,将各个分片里的数据汇总起来一并返回给客户端,因此 ElasticSearch 的节点需要有足够的 CPU 和内存资源去处理汇总操作;
Ingest Node(提取节点):能执行预处理管道,不负责数据也不负责集群相关的事务。

分片&副本

在 ElasticSearch 中的一个 Index 可以存储海量的 Document,单台机器的磁盘大小是无法存储的,而且在进行数据检索的时候,单台机器也存在性能瓶颈,无法为海量数据提供高效的检索。

为了解决上述问题,ElasticSearch 将单个 Index 分割成多个分片,创建 Index 时,可以按照预估值指定任意数量的分片。虽然逻辑上每个分片都属于一个 Index,但是单个分片都是一个功能齐全且独立的 Index,一个分片可以被分配到集群中的任意节点上。

通过分片的功能,Index 就有了容量水平扩展的能力,运维人员可以通过添加节点的方式扩充整个集群的容量。在处理检索请求时,不同的分片由不同的 ElasticSearch 节点进行检索,可以实现并发操作,这样也就可以大大提高检索性能。

最后,某条 Document 数据具体存储在哪个分片,完全由 ElasticSearch 的分片机制决定。当写入一条 Document 的时候,ElasticSearch 会根据指定的 key (默认是 ElasticSearch 自动生成的 Id,用户也可以手动指定)决定其所在的分片编号,计算公式如下:

复制代码
分片编号 = hash(key) % 主分片数量
主分片的数量决定了 Document 所在的分片编号,所以在创建 Index 之后,主分片数量不能改变。

在进行搜索时,每个分片产生的部分查询结果,也是由 ElasticSearch 集群负责进行聚合的,整个过程对于 Client 来说是透明的,如同操作一个单节点 ElasticSearch 实例。

单台服务器在实际使用中可能会因为这样或那样的原因发生故障,例如意外断电、系统崩溃、磁盘寿命到期等,这些故障是无法预知的。当发生故障时,该节点负责的分片就无法对外提供服务了,此时需要有一定的容错机制,在发生故障时保证此分片可以继续对外提供服务。

ElasticSearch 提供的副本功能就可以很好的解决这一问题,在副本模式下,每个分片分为主分片和副本分片,下图中一个 Index 有两个分片,p0 和 p1 是两个主分片,r0 和 r1 则是相应的副本分片:

在这里插入图片描述

副本带来了两个好处:一个是在主分片出现故障的时候,可以通过副本继续提供服务(所以,分片副本一般不与主分片分配到同一个节点上);另一个就是查询操作可以在分片副本上执行,因此可以提升整个 ElasticSearch 查询性能。

ElasticSearch 写入流程简介

分片是 ElasticSearch 中最小的数据分配单位,即一个分片总是作为一个整体被分配到集群中的某个节点。继续深入分片的结构会发现,一个分片是由多个 Segment 构成的,如下图所示:

在这里插入图片描述
Segment 是最小的数据存储单元,ElasticSearch 每隔一段时间会产生一个新的 Segment,用于写入最新的数据。旧的 Segment 是不可改变的,只能用于数据查询,是无法继续向其中写入数据的。

在很多分布式系统中都能看到类似的设计,这种设计有下面几点好处:

旧 Segment 不支持修改,那么在读操作的时候就不需要加锁,省去了锁本身以及竞争锁相关的开销;
只有最新的 Segment 支持写入,可以实现顺序写入的效果,增加写入性能;
只有最新的 Segment 支持写入,可以更好的利用文件系统的 Cache 进行缓存,提高写入和查询性能。
介绍完分片内部的 Segment 结构之后,接下来简单介绍一下 ElasticSearch 集群处理一个写入请求的大致过程:

写入请求会首先发往协调节点(Coordinating Node),之前提到,协调节点可能是 Client 连接上的任意一个节点,协调节点根据 Document Id 找到对应的主分片所在的节点。

接下来,由主分片所在节点处理写入请求,先是写入 Transaction Log 【很多分布式系统都有 WAL (Write-ahead Log)的概念,可以防止数据丢失】,而后将数据写入内存中,默认情况下每隔一秒会同步到 FileSystem Cache 中,Cache 中的数据在后续查询中已经可以被查询了,默认情况下每隔 30s,会将 FileSystem cache 中的数据写入磁盘中,当然为了降低数据丢失的概率,可以将这个时间缩短,甚至设置成同步的形式,相应地,写入性能也会受到影响。

写入其他副本的方式与写入主分片的方式类似,不再重复。需要注意的是,这里可以设置三种副本写入策略:

quorum:默认为 quorum 策略,即超过半数副本写入成功之后,相应写入请求即可返回给客户端;
one :one 策略是只要成功写入一个副本,即可向客户端返回;
all:all 策略是要成功写入所有副本之后,才能向客户端返回。
ElasticSearch 的删除操作只是逻辑删除, 在每个 Segment 中都会维护一个 .del 文件,删除操作会将相应 Document 在 .del 文件中标记为已删除,查询时依然可以查到,但是会在结果中将这些"已删除"的 Document 过滤掉。

由于旧 Segment 文件无法修改,ElasticSearch 是无法直接进行修改的,而是引入了版本的概念,它会将旧版本的 Document 在 .del 文件中标记为已删除,而将新版本的 Document 索引到最新的 Segment 中。

另外,随着数据的不断写入,将产生很多小 Segment 文件,ElasticSearch 会定期进行 Segment Merge,从而减少碎片文件,降低文件打开数,提升 I/O 性能。在 Merge 过程中可以同时根据 .del 文件,将被标记的 Document 真正删除,此时才是真正的物理删除。

在这里插入图片描述

ElasticSearch 查询流程简介

可以通过 doc id 来查询,会根据 doc id 进行 hash,判断出来当时把 doc id 分配到了哪个 shard 上面去,从那个 shard 去查询。

客户端发送请求到任意一个 node,成为 coordinate node 。

coordinate node 对 doc id 进行哈希路由,将请求转发到对应的 node,此时会使用 round-robin 随机轮询算法,在 primary shard 以及其所有 replica 中随机选择一个,让读请求负载均衡。

接收请求的 node 返回 document 给 coordinate node 。

coordinate node 返回 document 给客户端。

es 搜索数据过程

es 最强大的是做全文检索,就是比如你有三条数据:

java真好玩儿啊

java好难学啊

j2ee特别牛

你根据 java 关键词来搜索,将包含 java 的 document 给搜索出来。es 就会给你返回:java真好玩儿啊,java好难学啊。

客户端发送请求到一个 coordinate node 。

协调节点将搜索请求转发到所有的 shard 对应的 primary shard 或 replica shard ,都可以。

query phase:每个 shard 将自己的搜索结果(其实就是一些 doc id )返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。

fetch phase:接着由协调节点根据 doc id 去各个节点上拉取实际的 document 数据,最终返回给客户端。

写请求是写入 primary shard,然后同步给所有的 replica shard;读请求可以从 primary shard 或 replica shard 读取,采用的是随机轮询算法。

参考

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值