1、节点:Node
一个节点就是一个Elasticsearch的实例,可以理解为一个 ES 的进程。
注意
- 一个节点 ≠ 一台服务器
如下图为一个在本地启动的服务节点
下面两张图为同一个基于5节点的本地集群
GET _cat/nodes?v
通过 Head 插件查看集群节点信息
2、角色:Roles
角色是ES节点的重要属性,属于Elasticsearch的重要基础概念。
角色在分布式、可扩展的系统架构中发挥着至关重要的作用,但是在ES的应用技术中,不需要过分深入去理解不同角色的具体含义。
如果你已经对 ES 应用层面熟练掌握,请戳:进阶篇:第二章 Elastic分布式原理-角色
2.1 基本概念
在高可用系统架构中,节点角色发挥着至关重要的作用。如果前期没有对业务系统和技术架构做足准备,没有充分考虑后期的扩展问题,势必会为将来的性能优化留下潜在问题。
2.2 常见的角色
- 主节点(active master):一般指活跃的主节点,一个集群中只能有一个,主要作用是对集群的管理。
- 候选节点(master-eligible):当主节点发生故障时,参与选举,也就是主节点的替代节点。
- 数据节点(data node):数据节点保存包含已编入索引的文档的分片。数据节点处理数据相关操作,如 CRUD、搜索和聚合。这些操作是 I/O 密集型、内存密集型和 CPU 密集型的。监控这些资源并在它们过载时添加更多数据节点非常重要。
- 预处理节点(ingest node):预处理节点有点类似于logstash的消息管道,所以也叫ingest pipeline,常用于一些数据写入之前的预处理操作。
2.3 使用和配置方法
准确的说,应该叫节点角色,是区分不同功能节点的一项服务配置,配置方法为
node.roles: [ 角色1, 角色2, xxx ]
注意:
- 如果 node.roles 为缺省配置,那么当前节点具备所有角色
2.4 节点角色进阶讲解
3、索引:Index
3.1 索引是什么
索引在 ES 中所表述的含义和 MySQL 中的索引完全不同,在 MySQL 中索引指的是加速数据查询的一种特殊的数据结构,如 normal index。
而在 ES 中,索引表述的含义等价于 MySQL 中的表(仅针对 ES 7.x 以后版本),注意这里只是类比去理解,索引并不等于表。
3.2 索引的组成部分
- alias:即 索引别名,后续有单独讲解,基础篇不赘述,戳:ES中索引别名(alias)的到底有什么用
- settings:索引设置,常见设置如分片和副本的数量等。
- mapping:即映射,定义了索引中包含哪些字段,以及字段的类型、长度、分词器等。
3.3 扩展知识
在 ES 中,索引在不同的特定条件下可以表示三种不同的意思:
- 表示源文件数据:当做数据的载体,即类比为数据表,通常称作 index 。例如:通常说 集群中有 product 索引,即表述当前 ES 的服务中存储了 product 这样一张“表”。
- 表示索引文件:以加速查询检索为目的而设计和创建的数据文件,通常承载于某些特定的数据结构,如哈希、FST 等。例如:通常所说的 正排索引 和 倒排索引(也叫正向索引和反向索引)。就是当前这个表述,索引文件和源数据是完全独立的,索引文件存在的目的仅仅是为了加快数据的检索,不会对源数据造成任何影响,
- 表示创建数据的动作:通常说创建或添加一条数据,在 ES 的表述为索引一条数据或索引一条文档,或者 index 一个 doc 进去。此时索引一条文档的含义为向索引中添加数据。
4、类型:Type(ES 7.x 之后版本已删除此概念)
4.1 类型的基本概念
从 Elasticsearch 的第一个版本开始,每个文档都存储在一个索引中并分配一个映射类型。映射类型用于表示被索引的文档或实体的类型,例如 product 索引可能具有 user 类型和 order 类型。
每个映射类型都可以有自己的字段,因此该 user 类型可能有一个 user_name 字段、一个 title 字段和一个 email 字段,而该 order 类型可以有一个 content 字段、一个 title 字段,并且和 user 类型一样,也有一个user_name字段。
每个文档都有一个_type 包含类型名称的元数据字段,通过在 URL 中指定类型名称,可以将搜索限制为一种或多种类型:
GET product/user,order/_search { "query": { "match": { "user_name": "吕小布" } } }
4.2 为什么要删除 type 的概念
最初,“索引”类似于 SQL 数据库中的“数据库”,“类型”相当于“表”。即
元字段 | ES 6.x 及早期版本 | ES 7.x 及之后版本 |
_index | DataBase | Table |
_type | Table | 固定为:“_doc” |
_doc | Row | Row |
- 逻辑不合理:然而这是错误的类比,官方后来也意识到了这是个错误。在 SQL 数据库中,表是相互独立的。一个表中的列与另一个表中的同名列无关。对于映射类型中的字段,情况并非如此。
- 数据结构混乱:在 Elasticsearch 索引中,不同映射类型中具有相同名称的字段在内部由相同的 Lucene 字段支持。换句话说,使用上面的示例,类型中的 user_name 字段与 user 和 order 类型中的字段存储在完全相同的 user_name 字段中 ,并且两个 user_name 字段在两种类型中必须具有相同的映射(定义)。
- 影响性能:最重要的是,在同一索引中存储具有很少或没有共同字段的不同实体会导致数据稀疏并干扰 Lucene 有效压缩文档的能力。
基于以上原因,官方决定从 Elasticsearch 中删除映射类型的概念。
4.3 替代方案
每个文档类型的索引
第一种选择是为每个文档类型设置一个索引,而不是把 user 和 order 存储在单个索引中。这样索引彼此完全独立,因此索引之间不会存在字段类型冲突。
这种方法有以下好处:
- 避免了稀疏字段,数据更密集,有利于 Lucene 中对索引的压缩效率。
- 在全文搜索中用于评分的术语统计信息更可能准确,因为同一索引中的所有文档都表示单个实体。
- 索引粒度更小,方便动态优化每个索引的性能。比如可以分别为两个索引单独设置不同的分片数量
4.4 不同版本中的变化
ES 5.6.0
- 在索引上设置index.mapping.single_type: true将启用将在 6.0 中强制执行的单类型每索引行为。
- parent-child的join字段替换可用于 5.6 中创建的索引。
ES 6.x
- 在 5.x 中创建的索引将在 6.x 中继续发挥作用,就像在 5.x 中一样。
- 在 6.x 中创建的索引仅允许每个索引使用单一类型。该类型可以使用任何名称,但只能有一个。首选类型名称是_doc,以便索引 API 具有与 7.0 中相同的路径:
PUT {index}/_doc/{id}和POST {index}/_doc
- _type 名称不能再与 组合 形成_id字段_uid 。该_uid字段已成为该_id字段的别名。
- 新索引不再支持旧式的父/子,而应使用该 join字段。
- 不推荐使用_default_映射类型。
- 在 6.8 中,索引创建、索引模板和映射 API 支持查询字符串参数 ( include_type_name),该参数指示请求和响应是否应包含类型名称。它默认为true,并且应该设置为一个明确的值以准备升级到 7.0。不设置include_type_name 将导致弃用警告。没有显式类型的索引将使用虚拟类型名称_doc。
ES 7.x
不推荐在请求中指定类型。例如,索引文档不再需要文档type。新的索引 API 适用PUT {index}/_doc/{id}于显式 ID 和POST {index}/_doc 自动生成的 ID。请注意,在 7.0 中,_doc是路径的永久部分,表示端点名称而不是文档类型。
索引创建、索引模板和映射 API 中的include_type_name参数将默认为false. 完全设置参数将导致弃用警告。
_default_映射类型被删除 。
ES 8.x
不再支持在请求中指定类型。
该include_type_name参数被删除。
5、文档:Document
5.1 文档的基本结构:doc struct
5.2 元数据:mata data
所有的元字段均已下划线开头,为系统字段。
_index:索引名称
_id:文档 id。
_version:版本号
_seq_no:索引级别的版本号,索引中所有文档共享一个 _seq_no
_primary_term:_primary_term是一个整数,每当Primary Shard发生重新分配时,比如节点重启,Primary选举或重新分配等,_primary_term会递增1。主要作用是用来恢复数据时处理当多个文档的_seq_no 一样时的冲突,避免 Primary Shard 上的数据写入被覆盖。
5.3 源数据:source data
指业务数据,即最终写入的用户数据。
6、集群:Cluster
6.1 单体服务
所有的的服务依赖于同一个节点
缺点
- 处理能力(包括吞吐量、并发能力、和算力等)有限,当业务量不断增加时,单体服务无法满足。
- 所有的服务依赖于同一个节点,当该节点出现故障,服务就完全不可用,风险高,可用性差。
6.2 集群的概念
一张图理解什么是集群
6.3 自动发现
ES 是自动发现的,即零配置,开箱即用,无需任何网络配置,Elasticsearch 将绑定到可用的环回地址并扫描本地端口9300到9305连接同一服务器上运行的其他节点,自动形成集群。此行为无需进行任何配置即可提供自动集群服务。
6.4 核心配置
network.host:即提供服务的ip地址,一般配置为本节点所在服务器的内网地址,此配置会导致节点由开发模式转为生产模式,从而触发引导检查。
network.publish_host:即提供服务的ip地址,一般配置为本节点所在服务器的公网地址
http.port:服务端口号,默认 9200,通常范围为 9200~9299
transport.port:节点通信端口,默认 9300,通常范围为 9300~9399
discovery.seed_hosts:此设置提供集群中其他候选节点的列表,并且可能处于活动状态且可联系以播种发现过程。每个地址可以是 IP 地址,也可以是通过 DNS 解析为一个或多个 IP 地址的主机名。
cluster.initial_master_nodes:指定集群初次选举中用到的候选节点,称为集群引导,只在第一次形成集群时需要,如过配置了 network.host,则此配置项必须配置。重新启动节点或将新节点添加到现有集群时不要使用此设置。
基于内网配置集群
基于公网配置集群
6.5 集群的健康值检查
6.5.1 健康状态
- 绿色:所有分片都可用
- 黄色:至少有一个副本不可用,但是所有主分片都可用,此时集群能提供完整的读写服务,但是可用性较低。
- 红色:至少有一个主分片不可用,数据不完整。此时集群无法提供完整的读写服务。集群不可用。
新手误区:对不同健康状态下的可用性描述,集群不可用指的是集群状态为红色,无法提供完整读写服务,而不代表无法通过客户端远程连接和调用服务。
6.5.2 健康值检查
方法一:_cat API
GET _cat/health
返回结果如下
方法二:_cluster API
GET _cluster/health
返回结果如下
6.6 集群的故障诊断
集群常见故障诊断手段通常为:通过检查集群的健康状态,是否有节点未加入或者脱离集群,以及是否有异常状态的分片。可采取以下 API 完成对集群的故障诊断。
6.6.1 Cat APIs:
常用APIs:
- _cat/indices?health=yellow&v=true:查看当前集群中的所有索引
- _cat/health?v=true:查看健康状态
- _cat/nodeattrs:查看节点属性
- _cat/nodes?v:查看集群中的节点
- _cat/shards:查看集群中所有分片的分配情况
6.6.2 Cluster APIs
- _cluster/allocation/explain:可用于诊断分片未分配原因
- _cluster/health/ :检查集群状态
6.6.3 索引未分配的原因
- ALLOCATION_FAILED: 由于分片分配失败而未分配
- CLUSTER_RECOVERED: 由于完整群集恢复而未分配.
- DANGLING_INDEX_IMPORTED: 由于导入悬空索引而未分配.
- EXISTING_INDEX_RESTORED: 由于还原到闭合索引而未分配.
- INDEX_CREATED: 由于API创建索引而未分配.
- INDEX_REOPENED: 由于打开闭合索引而未分配.
- NEW_INDEX_RESTORED: 由于还原到新索引而未分配.
- NODE_LEFT: 由于承载它的节点离开集群而取消分配.
- REALLOCATED_REPLICA: 确定更好的副本位置并取消现有副本分配.
- REINITIALIZED: 当碎片从“开始”移回“初始化”时.
- REPLICA_ADDED: 由于显式添加了复制副本而未分配.
- REROUTE_CANCELLED: 由于显式取消重新路由命令而取消分配.
7、分片:Shard
7.1 分片的基本概念
如过用一句话来概括,分片可以理解为 索引的碎片。并且所有碎片都是可以无限复制的
7.2 分片的种类
- 主分片(primary shard):
- 副本分片(replica shard):
7.3 分片的基本策略
- 一个索引包含一个或多个分片,在7.0之前默认五个主分片,每个主分片一个副本;在7.0之后默认一个主分片。副本可以在索引创建之后修改数量,但是主分片的数量一旦确定不可修改,只能创建索引
- 每个分片都是一个Lucene实例,有完整的创建索引和处理请求的能力
- ES会自动再nodes上做分片均衡 shard reblance
- 一个doc不可能同时存在于多个主分片中,但是当每个主分片的副本数量不为一时,可以同时存在于多个副本中。
- 主分片和其副本分片不能同时存在于同一个节点上。
- 完全相同的副本不能同时存在于同一个节点上。
7.4 分片的作用和意义
- 高可用性:提高分布式服务的高可用性。
- 提高性能:提供系统服务的吞吐量和并发响应的能力
- 易扩展:当集群的性能不满足业务要求时,可以方便快速的扩容集群,而无需停止服务。