淘先锋技术网

首页 1 2 3 4 5 6 7

概述

集群角色

集群由多个Node组成,Node可以有不同的类型,通过下面配置文件设置:

../elasticsearch.yml:
    node.master: [true|false]
    node.data: [true|false]
  • node.master=true :作为master的候选节点,标志着此节点可以产于选举。
  • node.data=true :此节点作为数据节点,存储shard数据以及处理数据的写入、查询等。
  • 两者都为false的时候,说明此节点只担任请求转发、结果聚合工作,在处理大量请求的时候,可以达到负载均衡效果。

核心概念

Cluster 集群

ES集群由多个节点组成,“集群名称”作为一个集群的标识。

Node 节点

一个ES实例代表一个Node。

Node具有多种类型,一般这样组合节点的类型:

类型/说明主节点+数据节点数据节点客户端节点
node.mastertruefalsefalse
node.datatruetruefalse
有成为主节点资格,也存储数据不参与竞选,只存储数据不存储、不竞选,主要是针对海量请求进行负载均衡

shard 分片

在ES中,索引数据被分为多个分片进行存储。
分片分为主分片和副分片,分别处理写操作和读操作,副分片是复制主分片的数据。
这些分片(即主、副分片)分布在各个节点上。比如分布在1节点上的主分片,其副分片可能在2节点上。

image.png

搭建集群

集群配置(基于Docker搭建)

参考博客:https://www.cnblogs.com/evescn/p/16175547.html

环境说明

elasticsearch:7.14.0。
我将开启三个虚拟机,搭建ES集群,共三个节点。

Node1Node2Node3
IP192.168.204.181192.168.204.182192.168.204.183
域名es01es02es03
系统Ubuntu 18Ubuntu 18Ubuntu 18

host文件配置C:\Windows\System32\drivers\etc\hosts

192.168.204.181 es01
192.168.204.182 es02
192.168.204.183 es03

架构如下:
一个master节点,其它两个节点只存储数据

准备

下面操作分别在三台主机上进行:

  • 创建存放数据、日志的目录:mkdir /home/liangshijie/es_home/datamkdir /home/liangshijie/es_home/logs
  • 授予数据、日志目录的权限给管理员用户:sudo chown -R 1000:1000 /home/liangshijie/es_home

1000:1000 的意思是: <用户ID>:<用户组ID>
查看用户ID:id -u <用户名>
查看用户组ID:getent group <用户组名>

  • 放开防火墙端口:92009300

我使用ufw管理防火墙,开放端口的命令:ufw allow 9200、ufw allow 9300

使用docker-compose启动ES实例

现在,需要在三台主机上配置docker-compose.yml文件,然后使用docker-compose up -d 命令创建、运行容器(用户需要具备root权限)。

Node1

version: '3'
services:
  es:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0        # es镜像版本
    container_name: es
    network_mode: host
    environment:
      - node.name=node1                                                # 节点名称
      - cluster.name=my-es-cluster                                     # 集群名称
      - discovery.seed_hosts=es02,es03                                 # 其他节点的地址
      - cluster.initial_master_nodes=node1                             # 初始主节点
      - bootstrap.memory_lock=true                                     # 内存锁定以避免交换
      - network.publish_host=es01                                      # 握手之后,响应的地址(写主机地址)
      - http.publish_host=es01                                         # 写主机地址
      - transport.publish_host=es01                                    # 写主机地址
      - node.master=true                                               # 节点参与主节点的竞选
      - node.data=true                                                 # 节点存储数据
      - http.port=9200
      - transport.tcp.port=9300                                        # 节点内部数据传输端口
      # - http.cors.enabled=true
      # - http.cors.allow-origin="*"
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"                               # JVM堆内存设置
    ulimits:                                                           # 资源限制设置
      memlock:                                                         # 内存锁定限制
        soft: -1                                                       # 软限制为无限制
        hard: -1                                                       # 硬限制为无限制
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - /home/liangshijie/es_home/data:/usr/share/elasticsearch/data   # <主机目录>:<容器内目录>。此外,也可以使用docker默认的。注意,要保证目录权限足够
      - /home/liangshijie/es_home/logs:/usr/share/elasticsearch/logs
    ports:
      - 9200:9200                                                      # 对外暴露端口
      - 9300:9300                                                      # 对外暴露端口
  kibana:                                                              # 不需要kibana的可以移除
      image: kibana:7.14.0
      container_name: kibana
      restart: always
      environment:
        - TZ="Asia/Shanghai"
      ports:
        - 5601:5601
      volumes:
        - /home/liangshijie/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml:ro  # 根据实际情况修改kibana.yml文件路径
      depends_on:
        - es

补充 kibana.yml

server.name: kibana
server.host: "0.0.0.0"
#此处为es的master地址
elasticsearch.hosts: "http://es01:9200"
xpack.monitoring.ui.container.elasticsearch.enabled: true
i18n.locale: "zh-CN"

Node2


version: '3'
services:
  es:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0        # es镜像版本
    container_name: es
    network_mode: host
    environment:
      - node.name=node2                                                # 节点名称
      - cluster.name=my-es-cluster                                     # 集群名称
      - discovery.seed_hosts=es01,es03                                 # 其他节点的地址
      - cluster.initial_master_nodes=node1                             # 初始主节点
      - bootstrap.memory_lock=true                                     # 内存锁定以避免交换
      - network.publish_host=es02                                      # 握手之后,响应的地址(写主机地址)
      - http.publish_host=es02                                         # 写主机地址
      - transport.publish_host=es02                                    # 写主机地址
      - node.master=false                                              # 节点参与主节点的竞选
      - node.data=true                                                 # 节点存储数据
      - http.port=9200
      - transport.tcp.port=9300                                        # 节点内部数据传输端口
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"                               # JVM堆内存设置
    ulimits:                                                           # 资源限制设置
      memlock:                                                         # 内存锁定限制
        soft: -1                                                       # 软限制为无限制
        hard: -1                                                       # 硬限制为无限制
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - /home/liangshijie/es_home/data:/usr/share/elasticsearch/data   # <主机目录>:<容器内目录>。此外,也可以使用docker默认的。注意,要保证目录权限足够
      - /home/liangshijie/es_home/logs:/usr/share/elasticsearch/logs
    ports:
      - 9200:9200                                                      # 对外暴露端口
      - 9300:9300                                                      # 对外暴露端口

Node3


version: '3'
services:
  es:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0        # es镜像版本
    container_name: es
    network_mode: host
    environment:
      - node.name=node3                                                # 节点名称
      - cluster.name=my-es-cluster                                     # 集群名称
      - discovery.seed_hosts=es01,es02                                 # 其他节点的地址
      - cluster.initial_master_nodes=node1                             # 初始主节点
      - bootstrap.memory_lock=true                                     # 内存锁定以避免交换
      - network.publish_host=es03                                      # 握手之后,响应的地址(写主机地址)
      - http.publish_host=es03                                         # 写主机地址
      - transport.publish_host=es03                                    # 写主机地址
      - node.master=false                                              # 节点参与主节点的竞选
      - node.data=true                                                 # 节点存储数据
      - http.port=9200                            
      - transport.tcp.port=9300                                        # 节点内部数据传输端口
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"                               # JVM堆内存设置
    ulimits:                                                           # 资源限制设置
      memlock:                                                         # 内存锁定限制
        soft: -1                                                       # 软限制为无限制
        hard: -1                                                       # 硬限制为无限制
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - /home/liangshijie/es_home/data:/usr/share/elasticsearch/data   # <主机目录>:<容器内目录>。此外,也可以使用docker默认的。注意,要保证目录权限足够
      - /home/liangshijie/es_home/logs:/usr/share/elasticsearch/logs
    ports:
      - 9200:9200                                                      # 对外暴露端口
      - 9300:9300                                                      # 对外暴露端口

验证

任意访问一个地址:http://es01:9200/_cat/health?vhttp://es02:9200/_cat/health?vhttp://es03:9200/_cat/health?v

epochtimestampclusterstatusnode.totalnode.datashardsprireloinitunassignpending_tasksmax_task_wait_timeactive_shards_percent
169260653508:28:55my-es-clustergreen3314700000100.0%
  • cluster 集群名称
  • status集群状态 green代表健康;yellow代表分配了所有主分片,但至少缺少一个副本,此时集群数据仍旧完整;red代表部分主分片不可用,可能已经丢失数据。
  • node.total代表在线的节点总数量
  • node.data代表在线的数据节点的数量
  • shards 存活的分片数量
  • pri 存活的主分片数量 正常情况下 shards的数量是pri的两倍。
  • relo迁移中的分片数量,正常情况为 0
  • init 初始化中的分片数量 正常情况为 0
  • unassign未分配的分片 正常情况为 0
  • pending_tasks准备中的任务,任务指迁移分片等 正常情况为 0
  • max_task_wait_time任务最长等待时间
  • active_shards_percent正常分片百分比 正常情况为 100%

挂载配置文件(可选)

如果你要挂载配置文件(上述例子中,配置内容我全写在environment中了),
你可以在volumes中添加:- /xxxx/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro,将配置文件挂载到主机。
下面是一个yml的例子:

cluster.name: my-es-cluster   
node.name: node1
node.master: true
node.data: true

#network.host: 0.0.0.0
network.bind_host: 0.0.0.0
network.publish_host: 10.0.0.1
http.port: 9200
transport.tcp.port: 9300
http.cors.enabled: true
http.cors.allow-origin: "*"

discovery.zen.ping.unicast.hosts: ["es-master:9300", "es-node1:9300", "es-node2:9300"]
discovery.zen.minimum_master_nodes: 2
discovery.zen.ping_timeout: 5s

bootstrap.memory_lock: true
action.destructive_requires_name: true
cluster.initial_master_nodes: ["es-master"]

ingest.geoip.downloader.enabled: false

重要系统配置(可选)

参考来源官网:https://www.elastic.co/guide/en/elasticsearch/reference/7.5/system-config.html

禁用交换

防止部分JVM堆数据被交换到磁盘,降低性能。

方式一:禁用交换分区

  • 临时禁用
sudo swapoff -a
  • 永久禁用
# 备份
sudo cp /etc/fstab /etc/fstab.bak

# 编辑
sudo nano /etc/fstab

# 注释下面
# /dev/mapper/swap none swap sw 0 0

# 重启系统(建议)
sudo reboot


# 验证:无输出表示成功
cat /proc/swaps

方式二:配置 swappiness

sysctl 值 vm.swappiness 设置为1。

设置为1表示尽量减少对分页交换的使用,优先使用物理内存。

  • 临时设置
  • 永久设置
sudo vim /etc/sysctl.conf

# 末尾添加
vm.swappiness=1

# 更改生效
sudo sysctl -p

方式三:启用 bootstrap.memory_lock

在启动时将JVM的堆内存锁定在物理内存中,从而避免将堆内存交换到磁盘上的分页交换空间。这可以提高Elasticsearch的性能和稳定性,尤其在处理大量数据时非常有用。

# 1.打开配置文件,通常位于config目录下
vim elasticsearch.yml

# 2.添加配置
bootstrap.memory_lock: true

# 3.重启ES

# 4.验证:mlockall 值为 true,则表示内存已经成功锁定。
curl -X GET "localhost:9200/_nodes?filter_path=**.mlockall"GET _nodes?filter_path=**.mlockall


注意,启用 bootstrap.memory_lock 需要足够的操作系统权限。可能需要使用超级用户(root)权限来执行这些操作。

文件描述符

Elasticsearch 使用许多文件描述符或文件句柄。用完文件描述符可能是灾难性的,并且最有可能导致数据丢失。确保将运行 Elasticsearch 的用户打开的文件描述符的数量限制增加到 65536 或更高。

  • 在Docker上设置:--ulimit nofile=65536:65536
  • 验证
GET _nodes/stats/process?filter_path=**.max_file_descriptors
  • 也在主机上设置
vim /etc/security/limits.conf

* soft nofile 65536
* hard nofile 65536

虚拟内存

默认操作系统对 mmap 计数的限制可能太低,这可能导致内存不足异常。

在 Linux 上,可以通过以 root 身份运行以下命令来增加限制(临时):sysctl -w vm.max_map_count=262144

什么时候要调整?调整到什么数值?需要有待后续进一步探究。这里就不深入

线程数

Elasticsearch运行时涉及许多不同类型的线程,包括搜索线程、索引线程、后台线程等。适当的线程数设置可以确保不会出现过多的线程竞争和资源竞争,从而提高系统的性能。设置合理的线程数可以确保各个线程能够充分利用可用的CPU核心,提高并发处理能力。

确保 Elasticsearch 用户可以创建的线程数至少为4096。

  • 使用root运行命令
  • 或者将 nproc 设置为4096,添加到 /etc/security/limits.conf 配置文件中
sudo vim /etc/security/limits.conf

# 设置对应的es用户的nproc数值
es_user soft nproc 4096
es_user hard nproc 4096

# 重启系统

DNS缓存设置

Elasticsearch在运行时使用安全管理器(security manager)。在安全管理器下,Java虚拟机(JVM)默认会对主机名解析进行缓存,以提高性能。

Elasticsearch为了适应不同的环境和需求,对主机名解析的缓存行为进行了一些调整,并提供了修改缓存时间的选项。

默认将对正向主机名解析(从主机名到IP地址)的缓存时间设置为60秒,而对负向主机名解析(从IP地址到主机名)的缓存时间设置为10秒。

自定义缓存:

  • JVM选项中编辑 es.networkaddress.cache.ttles.networkaddress.cache.negative.ttl 的值,以自定义缓存时间。这些选项分别控制正向和负向主机名解析的缓存时间,单位为秒。

在Elasticsearch中,Java安全策略中的 networkaddress.cache.ttl 和 networkaddress.cache.negative.ttl 参数(用于修改缓存时间)是被忽略的。