节点:Node
- 一个节点就是一个ElasticSearch的实例,一个ES进程。负责存储数据、参与集群管理及处理客户端请求。
角色:Roles
角色(Node Roles) 定义了节点在集群中承担的具体职责。每个节点可以配置一个或多个角色,角色决定了节点能执行的操作和资源分配。
- 角色:通过
node.roles参数(在elasticsearch.yml中配置)定义,控制节点的功能。 如果node.roles参数为缺省配置,那么当前节点具备所有角色。 - 多角色节点:一个节点可以同时承担多个角色(如同时是数据节点和协调节点),但生产环境中通常建议角色分离,以提高性能和稳定性。
- 主节点 :
active master一般指活跃的主节点,一个集群只能有要给,主要作用时对集群的管理。 - 协调节点:
Coordinating Node是 Elasticsearch 集群中负责接收客户端请求、分发查询任务到相关分片,并最终汇总和返回结果的节点。 所有节点默认都是协调节点,除非显式禁用某些角色,否则任何节点(包括数据节点、主节点等)均可接收客户端请求,并充当协调节点。
常见的角色类型
| 中文角色名称 | 英文角色名称 | 核心作用 | 配置示例 |
|---|---|---|---|
| 主候选节点 | Master-eligible | 参与主节点选举,管理集群元数据(如索引创建、分片分配、节点加入/退出)。 | node.roles: [master] |
| 数据节点 | Data | 存储索引的分片数据,处理数据的写入、搜索、聚合等操作。 | node.roles: [data] |
| 预处理节点 | Ingest | 执行数据预处理管道(如解析日志、转换字段格式),再存储到索引中。 | node.roles: [ingest] |
| 仅投票节点 | Voting-only | 仅参与主节点选举投票,但不能成为主节点(需与 master 角色共存)。 |
node.roles: [master, voting_only] |
| 协调节点 | Coordinating | 接收客户端请求,路由到其他节点并聚合结果(默认所有节点均具备,可显式配置为专用协调节点)。 | node.roles: [](隐式角色) |
| 机器学习节点 | Machine Learning (ML) | 运行 Elasticsearch 的机器学习任务(需订阅许可证)。 | node.roles: [ml] |
| 远程集群客户端 | Remote Cluster Client | 支持跨集群搜索(Cross-Cluster Search),作为连接其他集群的客户端节点。 | node.roles: [remote_cluster_client] |
| 转换节点 | Transform | 运行 Transform 任务,生成聚合数据的物化视图(类似预计算)。 | node.roles: [transform] |
配置elasticsearch.yml
1 | # 多角色配置示例(主节点 + 数据节点) |
1 | # 禁用所有其他角色,仅保留协调功能 **显式配置专用协调节点** |
数据节点(Data Node) 的子类型
Elasticsearch 的数据分层(Data Tiers)包含以下角色:
| 角色名称 | 缩写 | 数据访问频率 | 存储成本 | 典型场景 |
|---|---|---|---|---|
data_hot |
DATA_HOT |
高 | 高 | 实时写入的热数据(如日志流) |
data_warm |
DATA_WARM |
中 | 中 | 近期查询的温数据(如上周报表) |
data_cold |
DATA_COLD |
低 | 低 | 历史数据(如月度备份) |
data_frozen |
DATA_FROZEN |
极少 | 最低 | 归档数据(如年度日志) |
data_content |
DATA_CONTENT |
依赖业务场景 | 可变 | 通用业务数据(非分层索引) |
数据节点(Data Node) 结合 ILM 策略
通过索引生命周期管理(ILM),自动将索引从 hot → warm → cold → frozen 迁移。
索引:Index
索引的定义
索引(Index)是存储和组织数据的逻辑单元,类似于关系型数据库中的数据库。它是一组文档(Document)的集合,每个文档包含一组字段(Field),这些字段存储实际数据。索引是 Elasticsearch 的核心概念,用于高效存储、检索和分析大规模数据。
- 类比:
- 索引 ≈ 数据库
- 文档 ≈ 数据库中的一行记录
- 字段 ≈ 数据库中的列
- 存储方式:索引的数据物理上存储在 Elasticsearch 集群的节点上,分片(Shards)和副本(Replicas)机制确保数据的分布和高可用性。
索引相关的配置部分
- alias
- setting
- mapping
索引的常见含义
“索引”(Index)这个词在不同上下文中可能有多种含义,具体取决于讨论的焦点场景。以下是常见的几种含义及其解释:
名词:逻辑数据容器(核心概念)
- 含义:索引是 Elasticsearch 中存储和组织的逻辑单元,类似于传统数据库中的“表”或“集合”。
- 作用:用于存储同一类数据(如日志、商品信息等)。
- 示例:
1
2# 创建一个名为 "logs" 的索引
PUT /logs - 关键特点:
- 每个索引有自己的映射(数据结构定义)和配置(如分片数、副本数)。
- 数据通过文档(JSON 格式)存储。
动词:写入数据(操作动作)
- 含义:将文档存储到 Elasticsearch 的过程称为“索引文档”(Indexing a Document)。
- 示例:
1
2
3
4
5
6# 向 "users" 索引中写入一条文档(动词)
POST /users/_doc/1
{
"name": "Alice",
"age": 30
} - 关键特点:
- 写入数据时会自动创建倒排索引(用于加速搜索)。
- 可以手动指定文档 ID,或让 Elasticsearch 自动生成。
数据结构:倒排索引(存储机制)
类型:Type
Type的类比
最初,Elasticsearch 团队为了让用户更容易上手,把结构设计得像关系型数据库:
- 一个 Index 类似数据库
- 多个 Type 类似表(table)
- Document 类似行(row)
| 元字段 | ES6.x及更早的版本 | ES7.x及以后的版本 |
|---|---|---|
_index |
DataBase |
Table |
_type |
Table |
固定为:_doc |
_doc |
Row |
document |
为什么要删除type概念
与 Lucene 的底层结构不兼容
Lucene 本身并没有“类型”的概念。它只处理扁平化的文档集合。Elasticsearch 是在 Lucene 的基础上,通过添加一个特殊的内部字段来模拟和管理type的。但这增加了复杂性。字段冲突
在同一个 Lucene 索引中,任何具有相同名称的字段,无论它来自哪个原始的 Elasticsearchtype,都必须遵守同一个字段定义和数据结构。Elasticsearch中不同type的相同字段名必须要有相同的数据结构,字段冲突和管理复杂性增加用户负担。稀疏字段
同一个索引中不同type存在时,在Lucene文档在索引时,多出来的大量缺少数据的冗余字段(稀疏字段)。稀疏数据不仅影响存储,还会对查询性能产生负面影响。一些底层数据结构(如用于排序和聚合的 Doc Values)在处理稀疏数据时效率较低,即使某个文档没有某个字段的值,仍然需要为其分配空间或进行处理。
文档:Document
文档(Document) 是存储和索引的基本数据单元,类似于关系型数据库中的一行记录。文档以 JSON 格式表示,包含一组字段(field)和对应的值,用于描述某个实体或对象。
元数据
_index: 指定文档所属的索引(index),类似于关系型数据库中的表名。_id:文档的唯一标识符,用于在索引中区分不同的文档。_version:记录文档的版本号,用于实现乐观并发控制(optimistic concurrency control)。_source:文档的原始 JSON 数据_routing:决定文档存储在哪个分片_seq_no:表示文档的序列号(sequence number),用于记录文档在主分片上的操作顺序。- 提供更细粒度的操作追踪,记录每个文档的创建、更新或删除操作的顺序。
- _seq_no 是分片级别的,每个主分片的序列号独立。
- 由主分片自动分配,从 0 开始递增。每个操作(创建、更新、删除)都会生成一个新的 _seq_no。
- 与 _primary_term 一起,用于实现更高效的并发控制(替代传统的 _version 在某些场景)。
- 支持全局排序,确保操作在分片间的顺序一致性。
_primary_term:表示主分片的任期(primary term),用于标识主分片的生命周期。- 由 Elasticsearch 集群在主分片分配时生成,从 1 开始递增。
- 每当主分片发生变更(如节点故障、主分片重新分配)时,_primary_term 会递增。
- 与 _seq_no 一起,唯一标识主分片上的操作,解决分片重新分配或故障恢复时的冲突。
_version vs _seq_no + _primary_term
_version:文档版本号,简单并发控制,适用于低并发场景,记录文档变更历史。_seq_no + _primary_term:更高效,适合高并发和复杂的分布式场景,是当前推荐的并发控制方案
联合使用方法:
- 读取文档时获取 seq_no 和 primary_term
- 更新文档时同时指定 if_seq_no 和 if_primary_term 参数
- 如果这两个值与当前文档不匹配,更新会失败
1 | // 获取文档,记录 seq_no 和 primary_term |
源数据
- 数据类型
- 文档的操作
- 文档搜索和聚合
- 文档并发控制
文档的存储
- 文档通过路由算法(默认基于 _id 的哈希值)分配到某个分片,确保数据均匀分布。
分片:Shard
- 索引的
碎片, 碎片可无限复制
分片的种类
- 主分片
primary shard - 副本分片
replica shard
分片的意义
- 高可用性: 容灾,提高分布式服务的高可用性
- 提高性能: 提高系统服务的吞吐量 和 并发响应能力
- 主分片: 主分片分配在多台服务上, 变相提供服务的写入能力
- 副本分片: 每个分片都能单独处理数据,可提高并发响应能力
- 易扩展性: 当集群的性能不满足业务需求时,分片的分配机制(replica、reblance)可以很方便的快速扩展集群,无需停止服务
路由机制
- 默认路由:使用文档的
_id字段计算哈希值,通过公式shard_num = hash(_id) % number_of_primary_shards确定目标分片。确保相同_id的文档始终路由到同一主分片。 - 自定义路由:用户可指定路由参数(如
routing=user_id),使相同路由值的文档分配到同一分片,优化查询效率。
分片数量固定
- 索引创建时需确定主分片数,后期无法更改,否则会导致路由计算不一致,需重新索引数据。
分片的分配策略
- 索引在不指定分片数量时,默认1个主分片和1个副本分片
- 索引一旦创建,只能修改副本分片数量,无法修改主分片数量(route原因)
- ES会自动在node上做分配均衡 shard reblance
- 每一个分片都是一个Lucene 实例,有完整的创建索引和处理请求的能力
- 主分片和其副本分片 不能同时存在于同一个节点上
- 完全相同的副本,不能同时存在于同一个节点上
集群:Cluster
集群工作原理
节点发现与加入
- 节点启动时通过配置的发现机制找到集群
- 使用 Zen Discovery(旧版)或 Zen2(7.0+版本)进行节点发现
- 通过集群状态更新保持节点间信息同步
主节点选举
- 集群通过选举机制选择一个主节点,负责管理集群状态。
- 如果主节点故障,集群会重新选举新主节点。
- 示例:3 个节点配置了 node.master: true,其中一个被选为主节点。
分片分配与负载均衡
- 主节点根据节点容量和配置,将主分片和副本分片分配到数据节点。
- 副本分片不会与主分片分配到同一节点,以确保高可用性。
- 示例:一个索引有 3 个主分片和 1 个副本分片,集群有 3 个数据节点,分片可能分配如下:
- 节点 1:主分片 1,副本分片 2
- 节点 2:主分片 2,副本分片 3
- 节点 3:主分片 3,副本分片 1
分布式查询
查询由协调节点处理,分为以下阶段:
- 查询分发:协调节点将查询发送到所有相关分片(主分片或副本分片)。
- 分片执行:每个分片在本地 Lucene 索引上执行查询,返回局部结果。
- 结果合并:协调节点合并分片结果,进行全局排序和分页,返回给客户端。
数据复制与故障恢复
- 写入操作首先应用于主分片,然后同步到副本分片。
- 如果主分片故障,副本分片可升级为主分片,主节点重新分配分片以恢复副本。
- 示例:节点 1 故障,存储主分片 1,集群将副本分片 1(在节点 2)提升为主分片,并分配新的副本分片到其他节点。
核心配置
network.hostnetwork.publish_hosthttp.porttransport.portdiscovery.seed_hostscluster.initial_master_nodes
集群健康
集群健康状态分为三级:
- 绿色(Green):所有主分片和副本分片都正常运行
- 黄色(Yellow):所有主分片正常,但有副本分片未分配
- 红色(Red):有主分片未分配,部分数据不可用
Cat APIs
_cat/indices?health=green&v查看集群中所有索引,按health条件过滤green,yellow,red_cat/health?v查看集群健康状态_cat/nodes?v看清集群中的节点_cat/shards查看集群中所有分片的分配情况_cat/nodeattrs查看节点属性
Cluster APIs
_cluster/allocation/explain诊断分片未分配原因_cluster/health/<target>检查集群状态
索引分片未分配的原因
集群扩展与高可用
- 水平扩展:添加节点增加存储容量和计算能力
- 分片分配:当节点加入或离开时,分片会自动重新分配
- 故障恢复:节点故障时主分片自动提升,保持数据可用性
- 跨数据中心部署:支持地理分布式部署实现灾难恢复
Elasticsearch 与 Lucene
- Elasticsearch 负责分布式架构、REST API、数据分片(Shards)和副本(Replicas)等高级功能。
- Elasticsearch 中每个索引由多个分片(shard)组成。每个分片(Shard)对应一个 Lucene 实例。
- Lucene 负责单个节点上的索引存储、查询和分析。
- 查询时,Elasticsearch 会在多个分片上并行处理请求,然后合并结果。
- 每个分片包含多个 Lucene 段,段是 Lucene 内部的存储单位。
- 在 Lucene 中,所有文档是扁平存储的,字段映射由 Elasticsearch 的映射(Mappings)定义。
Elasticsearch 与 Lucene 的关系
- 底层依赖:
Elasticsearch 是基于 Apache Lucene 构建的分布式搜索引擎。Lucene 提供了单机环境下的高性能全文检索能力(如倒排索引、分词、查询解析、排序等),而 ES 在其基础上扩展了分布式架构、RESTful API、数据分片、副本管理等能力。 - 分片与 Lucene 实例:
- ES 中的每个索引(Index)被划分为多个分片(Shard),每个分片是一个独立的 Lucene 索引实例。
- 分片分为主分片(Primary Shard)和副本分片(Replica Shard),每个分片(无论是主还是副本)均对应一个完整的 Lucene 索引。
- 例如:一个索引配置为5个主分片,则数据会被分散到5个独立的 Lucene 实例中存储和检索。
ES 分布式查询与排序的流程
当向 ES 发起查询时,其分布式处理流程分为两个核心阶段:
- 查询阶段(Query Phase)
- 取回阶段(Fetch Phase)
阶段1:查询阶段(Query Phase)
- 客户端发送查询请求:用户通过 REST API 发送查询请求到某个 Elasticsearch 节点(称为协调节点,Coordinating Node)。
- 解析查询:协调节点解析查询请求,确定需要查询的索引和分片。
- 分发查询:协调节点将查询广播到所有相关分片(包括主分片和副本分片)。Elasticsearch 使用路由机制确保只查询必要的分片。
- 分片级查询:每个分片在其本地 Lucene 索引上执行查询,生成一个局部结果集(包含文档 ID 和评分)。
- 结果汇总:各分片将局部结果返回给协调节点,协调节点合并这些结果,生成全局的候选结果集。
阶段2:取回阶段(Fetch Phase)
- 选择最终结果:协调节点根据查询的排序规则(如评分、字段值等)从候选结果集中选择最终的文档(例如前 N 条)。
- 获取完整文档:协调节点向持有相关文档的分片发送请求,获取完整的文档内容(或指定的字段)。
- 返回结果:协调节点将最终结果集整理后以 JSON 格式返回给客户端。
排序处理细节
- 分片级排序:每个分片根据查询的排序规则(如评分或字段值)对本地结果进行排序,并返回前 K 条结果(K 由查询参数决定)。
- 全局合并:协调节点收集所有分片的局部结果,合并成一个全局结果集,并根据排序规则重新排序。
- 优化机制:
- 早期终止:对于某些查询,Elasticsearch 可以在分片级别提前终止低评分的文档收集,以减少计算开销。
- 字段缓存:对于基于字段的排序,Elasticsearch 使用字段数据缓存(fielddata)或文档值(doc values)来加速排序。
- 近似排序:在某些场景下(如高分页查询),Elasticsearch 可能使用近似算法(如 search_after)以提高性能。
分布式查询和排序带来的问题
- 性能瓶颈:当分片数量过多或查询复杂时,协调节点的合并开销可能成为瓶颈。
- 一致性问题:由于分布式系统中的数据同步延迟,可能导致查询结果不完全一致(Elasticsearch 提供 refresh 和 wait_for 参数来控制一致性)。
- 深分页问题:高偏移的分页查询(如 from=10000)可能导致性能下降,建议使用 search_after。
总结
- ES 与 Lucene 的关系:Elasticsearch 是基于 Lucene 的分布式搜索平台,Lucene 提供底层的索引和搜索能力,而 Elasticsearch 提供了分布式架构和用户友好的接口。(mysql、innerdb)
- 分布式查询:通过查询分发和结果合并,Elasticsearch 实现高效的分布式搜索,分为查询阶段和获取阶段。
- 分布式排序:Elasticsearch 在分片级别进行局部排序,协调节点合并全局结果,并通过优化机制(如缓存、早期终止)提升性能。
Bootstrap Checks
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/bootstrap-checks.html
https://www.elastic.co/docs/deploy-manage/deploy/self-managed/bootstrap-checks
vm.max_map_count
1 | bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]; |
Elasticsearch 依赖内存映射文件管理索引,要求系统参数 vm.max_map_count 至少为 262144。若当前值过低(如默认的 65530),会触发引导检查失败。
解决方法
1 | # 编辑 sysctl 配置文件(选择适合你的方式) |
Memory lock check
Elasticsearch 要求启用内存锁定(bootstrap.memory_lock: true)的核心原因是为了避免内存交换(Swapping),从而保障服务的高性能和稳定性。
当操作系统物理内存不足时,会将部分内存数据转移到磁盘的交换区(Swap Space)。虽然这能暂时缓解内存压力,但对 Elasticsearch 这类高性能服务来说,内存交换会导致:
- 性能严重下降:磁盘读写速度比内存慢几个数量级,频繁交换会使请求延迟显著增加。
- 节点不稳定:若 Elasticsearch 进程的内存被交换出去,可能导致节点响应超时,被集群误判为离线,触发分片重新分配,进一步加重集群负载。
- 垃圾回收(GC)问题:JVM 堆内存若被交换,可能导致垃圾回收时间激增,甚至引发长时间停顿(Stop-the-World)。
elasticsearch.yml中添加配置
1 | bootstrap.memory_lock: true |
1 | bootstrap check failure [1] of [1]: memory locking requested for elasticsearch process but memory is not locked; for more information see [https://www.elastic.co/guide/en/elasticsearch/reference/8.18/bootstrap-checks-memory-lock.html] |
默认情况下,操作系统会限制用户进程锁定内存的能力。需通过 memlock unlimited 授予 Elasticsearch 用户无限制的内存锁定权限。
调整系统内存锁定限制
- **编辑
/etc/security/limits.conf**:1
vim /etc/security/limits.conf
- 在文件末尾添加以下内容(假设Elasticsearch运行用户为
es):1
2es soft memlock unlimited
es hard memlock unlimited
针对systemd系统的额外配置
- 编辑Elasticsearch的systemd服务文件:
1
vim /etc/systemd/system/elasticsearch.service
- 在
[Service]部分添加:1
LimitMEMLOCK=infinity
- 重新加载systemd配置并重启服务:
1
2sudo systemctl daemon-reload
sudo systemctl restart elasticsearch
验证
1 | curl -X GET "localhost:9200/_nodes?filter_path=**.mlockall" |
如果返回 "mlockall": true,则表示内存锁定已启用。
生成证书
1.生成证书
为Elasticsearch集群创建一个证书颁发机构。 密码 admin12345
bin/elasticsearch-certutil ca
2.为集群中的每个节点生成证书和私钥
bin/elasticsearch-certutil cert –ca elastic-stack-ca.p12
可以在创建过程中加入密码 admin12345
3.将证书拷贝到elasticsearch的每个节点下面config/certs目录下
elastic-certificates.p12
4.配置elasticsearch.yml文件
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12
5.如果在创建证书的过程中加了密码,需要将你的密码加入到你的Elasticsearch keystore中去。每个节点都需要
bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
systemctl 启动服务文件路径
1 | /usr/lib/systemd/system/ |
CA
password admin12345
GET _ssl/certificates
1 | cd /software/elasticsearch |
升级es 8.2到8.18.0
下载es
1 | wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.18.0-linux-x86_64.tar.gz |
证书安装
1 | pwd |
elasticsearch.yml
1 | cluster.name: shlog8-cluster |
创建 数据文件和日志文件目录
1 | cd /data |
jvm.options
1 | -Xms4g |
ik和pinyin分词器安装配置
项目历史原因ik 的字典和配置必须在config 目录下 analysis-ik
1 | cd /software/elasticsearch-8.18.0 |
[!Note] entitlement-policy
Starting with version 8.18, Entitlements replace SecurityManager as the security mechanism. Plugins must migrate their policy files to the new format. For more information, please refer to https://www.elastic.co/guide/en/elasticsearch/plugins/current/creating-classic-plugins.html
配置ik权限
1 | cd ./plugins/analysis-ik/ |
在entitlement-policy.yaml文件中添加配置
1 | ALL-UNNAMED: |
配置ik 字典
1 | cd ../../ |
1 |
|
安装pinyin分词器
1 | cd /software/elasticsearch-8.18.0 |
1 | scp -r ./elasticsearch-8.18.0/ es@10.104.33.105:/software/ |
1 | rm -rf /data/es818/* |
使用 ln -sfn 强制更新软连接的目标路径:
1 | ln -sfn /new/target /path/to/soft_link |
- 参数说明:
-s:创建符号链接。-f:强制覆盖现有链接。-n:避免将链接指向目录时的递归问题。
浏览器插件工具
- Multi Elasticsearch Heads
- Elasticsearch Tools
- Elasticvue