1、ElasticSearch 集群

1.1 ES 集群优势

Elasticsearch 集群是由多个节点组成的一个分布式系统。
使用 Elasticsearch 集群有以下几个优点:

  1. 扩展性:Elasticsearch 集群将数据分布在多个节点,也就是可以使用更多的 CPU、内存、磁盘等。从而能够进行大规模的数据存储和处理工作。随着数据不断的增长,可以通过向集群添加更多的节点来应对。这样即使数据量达到 PB 级别,Elasticsearch 集群仍可以正常工作。
    场景说明:应用程序每天生成数百万条日志。单个服务器可能很快就会被数据量压垮。使用 Elasticsearch 集群后,就可以将数据均匀分布到多个节点上,这样每个节点只需要负责处理一部分的数据,从而实现整体的扩展性,以应对大规模的数据增长。
  2. 数据的容灾:Elasticsearch 集群通过在多个节点上存储数据的副本,来实现数据的容灾。意味着,如果某个节点发生故障,数据仍然可以从其他节点的副本中快速恢复,无需人工干预,从而减少了业务中断的风险。从而保证了整个集群的正常运行。
  3. 服务的高可用性:Elasticsearch 集群具有自动检测节点故障的能力。当某个节点发生故障时,集群会将故障节点上的任务快速分配给其他正常运行的节点。这样,即使某个节点发生故障,整个集群仍可以继续正常运行。(用户几乎感觉不到任何影响。)

1.2 ES 如何组集群

  1. 单节点 ES,如下图所示;

  2. 如果单节点出现问题,服务就不可用了,新增一个 ES 节点加入集群

Elasticsearch 集群是由多个节点组成的,通过 cluster.name 定义集群名称,然后每个节点通过 node.name 来标识在集群中的名称。
cluster.name 相同则表示隶属于同一个集群。

2、ES 集群环境部署

2.0 环境地址规划

系统版本主机名称IP 地址
RockyLinux9 | Ubuntu2204kibana.wang.org192.168.80.150
RockyLinux9 | Ubuntu2204es-node1.wang.org192.168.80.151
RockyLinux9 | Ubuntu2204es-node2.wang.org192.168.80.152
RockyLinux9 | Ubuntu2204es-node3.wang.org192.168.80.153

2.1 node1 集群节点配置

# 1、安装 elasticSearch
[root@es-node1 ~]# yum install java-17-openjdk java-17-openjdk-devel -y
[root@es-node1 ~]# rpm -ivh elasticsearch-8.18.2-x86_64.rpm
[root@es-node1 ~]$ dpkg -i elasticsearch-8.18.2-amd64.deb

# 2、配置 elasticSearch
[root@es-node1 ~]# vim /etc/elasticsearch/elasticsearch.yml
cluster.name: es-cluster                # 集群名称
node.name: es-node1                     # 节点名称
path.data: /var/lib/elasticsearch       # 数据存储路径
path.logs: /var/log/elasticsearch       # 日志存储路径
# bootstrap.memory_lock: true           # 内存锁定,避免 es 使用 swap
network.host: 192.168.80.151            # 本机 IP 地址, 监听在本地哪个地址上
http.port: 9200                         # 监听端口
discovery.seed_hosts: ["192.168.80.151", "192.168.80.152", "192.168.80.153"]  # 集群主机列表
cluster.initial_master_nodes: ["192.168.80.151", "192.168.80.152", "192.168.80.153"]  # 参与选举的主机, 仅第一次启动集群时进行选举 [可以填写 node.name 的名称]
# 注释如下行重复配置 [重要]
# cluster.initial_master_nodes: ["es-node1.wang.org"]

# 关闭 Security
xpack.security.enabled: false
xpack.security.enrollment.enabled: false

# 3. 配置 JVM 内存
[root@es-node1 ~]# vim /etc/elasticsearch/jvm.options
-Xms512m
-Xmx512m

# 4. 重启 ES 服务
[root@es-node1 ~]# rm -rf /var/log/elasticsearch/*
[root@es-node1 ~]# systemctl restart elasticsearch
[root@es-node1 ~]# systemctl enable --now elasticsearch

2.2 node2 集群节点配置

# 1、安装 elasticSearch
[root@es-node2 ~]# yum install java-17-openjdk java-17-openjdk-devel -y
[root@es-node2 ~]# rpm -ivh elasticsearch-8.18.2-x86_64.rpm
[root@es-node2 ~]$ dpkg -i elasticsearch-8.18.2-amd64.deb

# 2、配置 elasticSearch
[root@es-node2 ~]# vim /etc/elasticsearch/elasticsearch.yml
cluster.name: es-cluster
node.name: es-node2
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 192.168.80.152            # 本机 IP 地址
discovery.seed_hosts: ["192.168.80.151", "192.168.80.152", "192.168.80.153"]
cluster.initial_master_nodes: ["192.168.80.151", "192.168.80.152", "192.168.80.153"]
# 注释如下行重复配置 [重要]
# cluster.initial_master_nodes: ["es-node2.wang.org"]

# 关闭 Security
xpack.security.enabled: false
xpack.security.enrollment.enabled: false

# 3. 配置 JVM 内存
[root@es-node2 ~]# vim /etc/elasticsearch/jvm.options
-Xms512m
-Xmx512m

# 4. 重启 ES 服务
[root@es-node2 ~]# rm -rf /var/log/elasticsearch/*
[root@es-node2 ~]# systemctl restart elasticsearch
[root@es-node2 ~]# systemctl enable --now elasticsearch

2.3 node3 集群节点配置

# 1、安装 elasticSearch
[root@es-node3 ~]# yum install java-17-openjdk java-17-openjdk-devel -y
[root@es-node3 ~]# rpm -ivh elasticsearch-8.18.2-x86_64.rpm
[root@es-node3 ~]$ dpkg -i elasticsearch-8.18.2-amd64.deb

# 2、配置 elasticSearch
[root@es-node3 ~]# vim /etc/elasticsearch/elasticsearch.yml
cluster.name: es-cluster
node.name: es-node3
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 192.168.80.153        # 本机 IP 地址
discovery.seed_hosts: ["192.168.80.151", "192.168.80.152", "192.168.80.153"]
cluster.initial_master_nodes: ["192.168.80.151", "192.168.80.152", "192.168.80.153"]

# 注释如下行重复配置 [重要]
# cluster.initial_master_nodes: ["es-node3.wang.org"]

# 关闭 Security
xpack.security.enabled: false
xpack.security.enrollment.enabled: false

# 3. 配置 JVM 内存
[root@es-node3 ~]# vim /etc/elasticsearch/jvm.options
-Xms512m
-Xmx512m

# 4. 重启 ES 服务
[root@es-node3 ~]# rm -rf /var/log/elasticsearch/*
[root@es-node3 ~]# systemctl restart elasticsearch
[root@es-node3 ~]# systemctl enable --now elasticsearch

3、ES 集群状态检测

3.1 ES 集群指标状态

Cluster Health 获取集群的健康状态,整个集群状态包括以下三种:

  1. green:健康状态,指所有主副分片都正常分配
  2. yellow:所有主分片都正常分配,但是有副本分片未正常分配
  3. red:有主分片未分配,也就是索引不完备,写可能有问题。(但不代表不能读取数据)

检查 ES 集群是否正常运行,可以通过 curl、Cerebro 两种方式。

curl http://127.0.0.1:9200/_cat/health
curl http://127.0.0.1:9200/_cat/nodes?v

3.2 Curl 命令检查集群状态

# 1、使用 curl 工具检查 ES 集群状态
[root@es-node3 ~]# curl http://192.168.80.151:9200/_cluster/health?pretty=true
{
  "cluster_name" : "es-cluster",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 36,
  "active_shards" : 72,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "unassigned_primary_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}

# 2、也可以编写脚本监控 ES 集群状态
curl -s http://192.168.80.151:9200/_cluster/health?pretty=true | grep "status" | awk -F '"' '{print $4}'
# 输出: green

3.3 安装 Cerebro 检查集群状态

cerebro 是可视化工具,用于检查 ES 集群状态。

RockyLinux9 部署 Cerebro

# 1、安装 java, 它目前仅支持 java1.8 版本
# 并不支持较高的 java 版本, "因此不要与 ES 安装在同一节点上"
[root@kibana ~]# yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel -y

# 2、安装 Cerebro
[root@kibana ~]# wget https://github.com/lmenezes/cerebro/releases/download/v0.9.4/cerebro-0.9.4-1.noarch.rpm
[root@kibana ~]# rpm -ivh cerebro-0.9.4-1.noarch.rpm

# 3、配置 Cerebro
[root@kibana ~]# vim /etc/cerebro/application.conf
data.path: "/var/lib/cerebro/cerebro.db"
# data.path = "./cerebro.db"

# 4、启动 Cerebro
[root@kibana ~]# systemctl start cerebro

# 查看端口
[root@kibana ~]# netstat -lntp
Proto Recv-Q Send-Q Local Address   Foreign Address     State       PID/Program name
tcp6       0      0 :::9000         :::*                LISTEN     504/java

Ubuntu2204 部署 Cerebro

# 可以将其安装在 Kibana 主机
# 依赖 JDK-11
[root@ubuntu2204 ~]# apt -y install openjdk-11-jdk

# 下载包, 官方提供了 DEB 和 RPM 包
[root@ubuntu2204 ~]# wget https://github.com/lmenezes/cerebro/releases/download/v0.9.4/cerebro_0.9.4_all.deb

# 安装
[root@ubuntu2204 ~]# dpkg -i cerebro_0.9.4_all.deb

# 启动
[root@ubuntu2204 ~]# systemctl start cerebro.service

# 默认服务无法启动, 端口无法打开
[root@ubuntu2204 ~]# ss -ntlp | grep 9000

# 默认无法启动, 查看日志, 可以看到以下提示, 原因是默认 cerebro.db 文件所有目录没有权限导致
[root@ubuntu2204 ~]# journalctl -u cerebro
# 报错: Caused by: java.sql.SQLException: opening db: './cerebro.db': 权限不够

# 修改配置文件
[root@ubuntu2204 ~]# vim /etc/cerebro/application.conf
data.path: "/var/lib/cerebro/cerebro.db"  # 取消此行注释
# data.path = "./cerebro.db"              # 注释此行, 默认路径是 /usr/share/cerebro/cerebro.db

# 此目录自动生成
[root@ubuntu2204 ~]# ll -d /var/lib/cerebro
drwxr-xr-x 2 cerebro cerebro 4096   4月 10     2021 /var/lib/cerebro/

# 重启服务
[root@ubuntu2204 ~]# systemctl restart cerebro.service
[root@ubuntu2204 ~]# systemctl enable --now cerebro.service

# 默认监听 9000 端口
[root@ubuntu2204 ~]# ss -ntlp | grep 9000
LISTEN   0   100   *:9000           *:*         users:(("java",pid=26333,fd=155))

# 访问下面链接地址
http://192.168.80.150:9000

访问 Cerebro 页面

Node address 输入框中输入任意 ES 集群节点的地址:http://192.168.80.151:9200

4、ES 集群节点类型

ES 集群中节点类型介绍:

  • Master
  • Data
  • Ingest
  • Coordinating

4.1 Cluster State

Cluster State 是用来存储 Elasticsearch 集群相关的元数据信息。它存储在每个节点上,主要包含以下信息:

  • 节点信息:这部分信息包括节点名称或节点的IP、节点的 IP 地址或端口等。
  • 索引元数据:这部分信息包括索引的名称、索引的配置设置(如分片数量、副本数量等)以及字段类型和属性等。

4.2 Master 角色

  1. Elasticsearch 集群中只能有一个处于激活状态的 Master 节点。Master 节点负责管理和控制整个集群的操作;
  2. Master 节点负责维护集群状态(Cluster State)。当集群状态发生变化(例如,新增或删除索引、修改索引设置等)时,Master 节点会将更新后的集群状态同步给其他节点,以保持整个集群的状态一致性。
  3. Master 节点是通过选举产生的。集群中的节点可以设置 node.master: true 来允许它成为 Master 节点的候选者(默认为 true)。如果当前的 Master 节点失效或不可用时,集群会自动触发选举过程,从候选者中选出一个新的 Master 节点。
版本角色配置
7.X 版本Master 角色:
node.master: true
node.data: false
Data 角色:
node.master: false
node.data: true
Coordinating 角色:
node.master: false
node.data: false
8.X 版本Master 角色:
node.roles: ["master","data"] (既当 master, 又当 data)
Data 角色:
node.roles: ["data"]
Coordinating 角色:
node.roles: []

4.3 Data 角色

Data 节点是 Elasticsearch 集群中负责存储数据的节点。默认情况下,集群中的所有节点都是 Data 类型。

  1. 可以通过设置 node.data: true(默认为 true)来保持节点作为 Data 节点。
  2. 当创建索引后,索引中的数据会被存储在一个或多个 Data 节点上。这些能够存储索引数据的节点被称为 Data 节点。Data 节点负责处理数据查询、聚合和搜索等操作,它们直接影响整个集群的性能和存储能力。

通过合理分配和管理 Data 节点,可以提高 Elasticsearch 集群的数据处理能力、查询性能和存储容量。在实际应用中,需要根据业务需求和硬件资源来调整 Data 节点的数量和配置。

4.4 Ingest 角色

Ingest 节点是 Elasticsearch 集群中负责预处理文档的过程,它允许文档在被写入到 Elasticsearch 之前,对其进行处理、清洗、或转换。

  1. 假设你有一个包含日志数据的 JSON 文档,其中包含一个时间戳字段,但格式不符合标准。我们就可以在文档被写入之前,使用 date 处理器来转换时间戳字段的格式。
  2. node.ingest: true 表示该节点可以对文档进行预处理操作。如果你希望某个节点不处理 Ingest 任务,可以设置为 false。

4.5 Coordinating 角色

处理请求的节点被称为 Coordinating 节点。Coordinating 节点是 Elasticsearch 集群中所有节点的默认角色,无法取消。

  1. Coordinating 节点主要负责将请求路由到正确的节点。例如,创建索引的请求会被 Coordinating 节点路由到 Master 节点进行处理,而数据查询或写入的请求会被路由到相应的 Data 节点上。
  2. 当一个节点同时设置 node.master:falsenode.data:false 时,该节点仅充当 Coordinating 路由节点的角色。

4.6 角色设定示例

  1. 如果希望节点只作为主节点
    # ES7.X
    node.master: true
    node.data: false
    
    # ES8.X
    node.roles: ["master", "ingest"]    # 只做 master, 不当 data
    
  2. 如果希望节点只作为数据节点
    # ES7.X
    node.master: false
    node.data: true
    
    # ES8.X
    node.roles: ["data", "ingest"]    # 只当 data, 不做 master
    
  3. 如果希望节点同时担任数据节点和主节点
    # ES7.X
    node.master: true
    node.data: true
    
    # ES8.X
    node.roles: ["master", "data", "ingest"]    # 同时担任 master data
    
  4. 如果希望节点不担任任何特定角色(不推荐)
    # ES7.X
    node.master: false
    node.data: false
    
    # ES8.X
    node.roles: []    # 不担任任何角色
    

5.案例演示

# 修改 ES 配置
root@es-node1: vim /etc/elasticsearch/elasticsearch.yml
node.roles: ["data", "ingest"]    # 不做 master 节点 (默认每个节点都存在: master data ingest)

# 重启 ES 服务
root@es-node1: systemctl restart elasticsearch

5、ES 集群分片

5.1 什么是分片

分片是处理和存储 PB 级别数据的基础。在 Elasticsearch 中,分片是一种数据分区机制,它允许将一份完整的数据分散存储到集群的多个不同服务器上。而每个分片只是索引的一个部分,这使得它们可以独立进行存储和查询。

在 Elasticsearch 中,分片又被分为了两种类型:

  1. 主分片:主要负责存储数据。创建后主分片的数量是固定的(不允许修改)。
  2. 副本分片:每个主分片可以配置一个或多个副本分片,以增强数据的容错能力。副本分片从对应的主分片同步数据,确保在主分片出现问题时仍能提供服务。

5.2 什么是副本分片

副本分片主要用于提高数据的可用性,这样即使某个节点发生故障,系统依然可以自动从其他节点上的副本分片中恢复,并继续提供数据访问服务。

如下图所示,node2 上是 oldwang_index 索引的一个完整副本数据。

5.3 ES 集群如何增大容量

  1. 如下 3 个节点的 ES 集群,创建了一个 oldwang_index 索引,同时指定了 3 个分片,和 1 个副本
    # 创建索引, 设定主分片和副本分片
    PUT /oldwang_index
    {
        "settings": {
        "index": {
            "number_of_shards": 3,    # 主分片
            "number_of_replicas": 1   # 副本分配
        }
    }
    }
    
    # 动态修改副本分片
    PUT /oldwang_index/_settings
    {
        "number_of_replicas": 2    # 三节点,三分片. 因此最多只需要两副本就完全够了.
    }
    

问题:目前一共有 3 个 ES 节点,如果此时增加一个新节点 是否能提高 oldwang_index 索引数据容量?
答案:不能,因为 oldwang_index 只有 3 个分片,已经分布在 3 台节点上,那么新增的第四个节点对于 oldwang_index 而言是无法使用到的。所以也无法带来数据容量的提升。

5.4 ES 集群如何增加读性能

问题:目前一共有 3 个 ES 节点,如果增加副本数是否能提高 oldwang_index 索引的读性能?
答案:不能,因为新增的副本还是会分布在这 node1、node2、node3 这三个节点上的,还是使用了相同的资源,也就意味着有读请求来时,这些请求还是会分配到 node1、node2、node3 上进行处理、也就意味着,还是利用了相同的硬件资源,所以不会提升读性能。

问题:如果需要增加读吞吐量性能,应该怎么来做?
答案:增加读吞吐量还是需要添加节点,比如在增加三个节点 node4、node5、node6 那么将原来的 R0、R1、R2 分别迁移至新增的三个节点上,当有读请求来时会被分配 node4、node5、node6,也就意味着有新的 CPU、内存、IO,这样就不会在占用 node1、node2、node3 的硬件资源,那么这个时候读吞吐量才会得到真正的提升。

5.5 ES 副本与分片总结

分片数和副本的设定非常重要,需要在集群部署前进行仔细规划:

  1. 分片过小:可能导致在后续需要水平扩容时无法通过增加节点来实现,因为数据已经在现有节点上达到了分布的极限。
  2. 分片过大:可能会导致单个节点上分布过多的分片,从而造成资源的浪费。此外,过多的分片也会影响 ES 的查询性能。

6、ES 集群故障转移

6.1 什么是故障转移

所谓故障转移指的是,当集群中有节点发生故障时,这个集群是如何进行自动修复的。
ES 集群目前是由 3 个节点组成,此时集群状态是 green。

6.2 模拟节点故障案例

假设:node1 所在机器宕机导致服务终止,此时 ES 集群会如何处理;大体分为三个步骤:

  1. 重新选举

  2. 主分片调整

  3. 副本分片调整

  4. 重新选举阶段:node2 和 node3 发现 node1 无法响应;一段时间后会发起 master 选举。此时集群状态变为 Red 状态,假定选择 node2 为 master 节点;

  5. 主分片调整阶段:node2 发现主分片 P0 未分配,将 node3 上的 R0 提升为主分片。此时所有的主分片都正常分配,集群状态变为 Yellow 状态;

  6. 副本分片调整阶段:node2 将 P0 和 P1 主分片 重新生成新的副本分片 R0、R1。此时集群状态变为 Green;

7、ES 文档路由原理

ES 文档分布式存储,当一个文档存储至 ES 集群时,存储的原理是什么样的?
如图所示,当我们想在一个集群保存文档时,Document1 是如何存储到分片 P1 的?选择 P1 的依据是什么?

其实是有一个 文档到分片的映射算法,其目的是使所有文档均匀分布在所有的分片上。ES 既不使用随机算法,也不使用轮询算法,而是通过以下公式计算文档对应的分片:

shard = hash(routing) % number_of_primary_shards
  • hash:算法保证将数据均匀分散在分片中
  • routing:是一个关键参数, 默认是文档 id, 也可以自定义。
  • number_of_primary_shards:主分片数(与主分片取模)

注意:该算法与主分片数相关,一旦确定后便不能更改主分片。因为一旦修改主分片数量,shard 的计算结果就会完全不一样,会导致无法定位到原有数据。

总结:ES 用 hash(routing) % 主分片数 来把文档分配到对应分片,确保分布均衡且可定位,因此主分片数不能改,否则找不到数据。

7.1 文档的创建流程

  1. 客户端发送请求:请求发送到任意节点(协调节点)。
  2. 路由计算:协调节点 根据文档 ID 计算分片号:shard = hash(document_id) % 主分片数量
  3. 定位主分片:找到对应的主分片所在节点。
  4. 主分片写入:写入内存 + translog,同时转发给副本分片。
  5. 副本写入:副本分片完成相同写入操作。
  6. 写入成功:所有副本确认后,最终返回成功响应给客户端。

7.2 文档的读取流程

  1. 客户端发起查询请求:发送到任意节点(协调节点)。
  2. 协调节点分发请求到所有分片:查询是并行的,包括主分片和副本分片中任选一个。
  3. 每个分片独立查询:每个分片返回自己的匹配结果(文档 + 分数等)。
  4. 协调节点合并结果:统一排序、分页等,生成最终结果。
  5. 返回客户端:查询结果发送回客户端。

7.3 文档批量创建的流程

(原文未补充内容)

7.4 文档批量读取的流程

(原文未补充内容)

8、ES 集群节点扩展

8.1 环境准备

系统版本主机名称IP 地址
RockyLinux9es-node4192.168.80.154
RockyLinux9es-node5192.168.80.155

8.2 ES 扩展 Data 节点

[root@node4 ~]# grep "^[a-Z]" /etc/elasticsearch/elasticsearch.yml
cluster.name: es-cluster            # 集群名称
node.name: es-node4                 # 节点名称
node.roles: ["data", "ingest"]      # ES8.x 配置 Data 节点, 不参与 Master 选举
http.port: 9200
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 192.168.80.154        # 内网 IP 地址
# bootstrap.memory_lock: true
discovery.seed_hosts: ["192.168.80.151", "192.168.80.152", "192.168.80.153"]

# Enable security features
xpack.security.enabled: false
xpack.security.enrollment.enabled: false

# ES7.X 配置方式
# node.data: true          # Data 节点
# node.master: false       # 不参与 Master 选举

[root@node4 ~]# systemctl restart elasticsearch

访问 CereBro 验证节点,路径:Nodes > Data 角色

8.3 ES 扩展 Coordinating 节点

[root@node5 ~]# grep "^[a-Z]" /etc/elasticsearch/elasticsearch.yml
cluster.name: es-cluster                # 集群名称
node.name: es-node5                     # 节点名称
node.roles: []                          # ES8 配置 Coordinating 节点
http.port: 9200
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
# bootstrap.memory_lock: true
network.host: 192.168.80.155             # 内网 IP 地址
discovery.seed_hosts: ["192.168.80.151", "192.168.80.152", "192.168.80.153"]
# Enable security features
xpack.security.enabled: false
xpack.security.enrollment.enabled: false

# ES7.X 配置方式
# node.data: false     # 不参与 Data 节点
# node.master: false   # 不参与 Master 选举

[root@node5 ~]# systemctl restart elasticsearch

8.4 节点扩展检查

通过 cerebro 检查集群扩展后的状态。
如果出现集群无法加入、或者加入集群被拒绝,尝试删除 /var/lib/elasticsearch 下的文件,然后重启 ES:

[root@node5 ~]# rm -rf /var/lib/elasticsearch/*
[root@node5 ~]# systemctl restart elasticsearch

如果将 data 节点修改为 Coordinating 节点,需要清理数据,否则无法启动:

# repurpose 重新调整
[root@node5 ~]# /usr/share/elasticsearch/bin/elasticsearch-node repurpose
------------------------------------------------------------------------
WARNING: Elasticsearch MUST be stopped before running this tool.

Found 1 indices (1 shards and 1 index meta data) to clean up
Use -v to see list of paths and indices affected
Node is being re-purposed as no-master and no-data. Clean-up of index data will be performed.
Do you want to proceed?
Confirm [y/N] y
Node successfully repurposed to no-master and no-data.

访问 CereBro 验证节点,路径:Nodes > Coordinating 角色

9、ES 集群调优建议

9.1 内核参数优化

  1. 内核参数优化
    [root@node ~]# vim /etc/sysctl.conf
    fs.file-max=655360                        # 设定系统最大打开文件描述符数, 建议修改为 655360 或者更高;
    vm.max_map_count = 262144                 # 用于限制一个进程可以拥有的虚拟内存大小, 建议修改成 262144或更高。
    net.core.somaxconn = 32768                # 设置系统允许的最大套接字监听(TCP SYN)队列长度;
    net.ipv4.tcp_tw_reuse = 1                 # 启用 TCP TIME-WAIT 状态的套接字重用。
    # net.ipv4.ip_local_port_range = 1000 65535 # 设置本地端口范围, 即操作系统分配给本地套接字的端口号范围。
    net.ipv4.tcp_max_tw_buckets = 400000      # 表示操作系统允许 TIME_WAIT 数量的最大值, 如果超过这个数字,TIME_WAIT套接字将立刻被清除
    
    [root@node ~]# sysctl -p
    
  2. 调整用户最大进程数(nproc),调整进程最大打开的文件描述符(nofile)
    [root@node ~]# rm -f /etc/security/limits.d/20-nproc.conf     # 删除默认 nproc 设定文件
    [root@node ~]# vim /etc/security/limits.conf
    *                soft    core           unlimited
    *                hard    core           unlimited
    *                soft    nproc          1000000
    *                hard    nproc          1000000
    *                soft    nofile         1000000
    *                hard    nofile         1000000
    *                soft    memlock        32000
    *                hard    memlock        32000
    *                soft    msgqueue       8192000
    *                hard    msgqueue       8192000
    

9.2 配置参数优化

# 1. 启用内存锁定, 避免 ES 使用 swap 交换分区, 频繁的交换, 会导致 IOPS 变高.
[root@es-node ~]# vim /etc/elasticsearch/elasticsearch.yml
bootstrap.memory_lock: true

# 2. 当 ES 配置内存锁定后, 需要确保操作系统允许 Elasticsearch 进程锁定足够的内存.
[root@es-node ~]# sed -i '/\[Service\]/a LimitMEMLOCK=infinity' /usr/lib/systemd/system/elasticsearch.service

# 3. 重新启动 elasticSearch
[root@es-node ~]# systemctl daemon-reload
[root@es-node ~]# systemctl restart elasticsearch

9.3 JVM 参数优化

9.3.1 基础原则

要估算 JVM 内存配置,主要看两点:

  • 要存多少数据
  • 有多少个节点(服务器)

经验公式:1GB 内存 可以支持 48GB ~ 96GB 的数据量(通常按 1:48 来算最保险)
单个主分片大小最好控制在 30GB~50GB

9.3.2 怎么估算内存和分片?

第一步:算出实际需要存储的数据量

实际存储量 = 总数据量 × (副本数 + 1)    // 因为副本也要占空间

例如:总数据量 1TB + 副本数据 → 实际存储数据量 2TB

第二步:算每个节点要存多少数据

每节点存储 = 实际数据量 ÷ 节点数    // 再加上 20% 预留空间

示例:实际存储量 2TB / 3 节点 + 20% 预留空间 → 每节点存储 850G

第三步:算每个节点需要多少内存

节点内存 ≈ 每节点存储量 ÷ 48(按1:48比例来算)

示例:每节点存储量 850G ÷ 48 → 节点内存 17 G

第四步:算分片数量(用于 ES)

主分片数量 = 总数据量 ÷ 30GB(建议一个分片控制在 30GB 左右)
总分片数 = 主分片数 × (副本数 + 1)

示例:主分片数量 ≈ 33 → 总分片数 ≈ 66

9.3.3 两个简单例子

示例 1:1TB 数据,3 个节点,1 个副本

  1. 实际要存:1TB × (1 + 1) = 2 TB
  2. 每节点:2TB ÷ 3 ≈ 700GB → 加 20% ≈ 850GB // 单节点实际存储
  3. 内存需求:850GB ÷ 48 ≈ 17GB // 单节点建议内存 17 * 2 ≈ 34G
  4. JVM 配置:每个节点内存 17GB
  5. 分片数量:1TB ÷ 30GB ≈ 33 个主分片
  6. 总分片数 = 33 × 2 = 66 个
  7. 单个索引分片数
    a. 每日数据量 ÷ 30G = (总数据量 ÷ 保留天数)÷ 30G
    b. 100 ÷ 30G = 3 分片 // 每天 100G 日志
    c. 1024 ÷ 30G = 33 分片 // 每天 1024G 日志

示例 2:2TB 数据,3 个节点,1 个副本

  1. 实际要存:2TB × 2 = 4TB
  2. 每节点:4TB ÷ 3 ≈ 1.4TB → 加 20% ≈ 1.7TB // 单节点存储
  3. 内存需求:1.7TB ÷ 48 ≈ 35GB → 超过建议上限(31GB)→ ⚠️ 不够用,得加节点!

增加到 4 个节点

  1. 每节点:4TB ÷ 4 = 1TB → 加 20% ≈ 1.2TB
  2. 内存需求:1.2TB ÷ 48 ≈ 25GB → 合理!
  3. 分片数量:2TB ÷ 30GB = 60 个主分片 → 总分片数 = 60 × 2 = 120个

结论:用 4 个节点,内存控制在 31GB 以内,刚刚好!

9.3.4 生产环境建议

  • 每天数据量:约 1TB
  • 机器配置:16 核,64GB 内存,6TB 磁盘(3 台 ECS)
  • JVM 设置:最大和最小内存都设为 31GB
  • 最好不要超过 32GB(超过后 JVM 的内存优化会失效)
  • ES 清理策略:只保留最近 1~2 周的数据,避免磁盘被撑爆。

结论

  • 每天数据约 1TB,建议单分片控制在 30~50GB,1TB / 30GB ≈ 每天 33 个主分片。
  • 实际存储量 = 日志量 × (副本数 + 1),估算内存按 1:48 比例。
  • JVM 不建议超过 31GB,超过后 G1 GC 优化失效。
  • 索引清理建议使用 ILM,仅保留最近 1~2 周数据,避免磁盘撑满。

此文章已被阅读次数:正在加载...更新于

请我喝[茶]~( ̄▽ ̄)~*

Jaxx.Wang 微信支付

微信支付

Jaxx.Wang 支付宝

支付宝