Elasticsearch集群管理

集群规划

搭建一个集群我们需要考虑如下几个问题:

1
2
3
4
5
1. 我们需要多大规模的集群?
2. 集群中的节点角色如何分配?
3. 如何避免脑裂问题?
4. 索引应该设置多少个分片?
5. 分片应该设置几个副本?

我们需要多大规模的集群

需要从以下两个方面考虑:

当前的数据量有多大?数据增长情况如何?

你的机器配置如何?cpu、多大内存、多大硬盘容量?

推算的依据:

1
2
ES JVM heap 最大可以设置32G 。
30G heap 大概能处理的数据量 10 T。如果内存很大如128G,可在一台机器上运行多个ES节点实例。

备注:集群规划满足当前数据规模+适量增长规模即可,后续可按需扩展。

两类应用场景:

1
2
A. 用于构建业务搜索功能模块,且多是垂直领域的搜索。数据量级几千万到数十亿级别。一般2-4台机器的规模。
B. 用于大规模数据的实时OLAP(联机处理分析),经典的如ELK Stack,数据规模可能达到千亿或更多。几十到上百节点的规模。

集群中的节点角色如何分配

** 节点角色 **

1
2
3
4
5
6
Master
node.master: true 节点可以作为主节点
DataNode
node.data: true 默认是数据节点。
Coordinate node 协调节点
如果仅担任协调节点,将上两个配置设为false。

说明:

一个节点可以充当一个或多个角色,默认三个角色都有

协调节点:一个节点只作为接收请求、转发请求到其他节点、汇总各个节点返回数据等功能的节点。

** 如何分配 **

1
2
A. 小规模集群,不需严格区分。
B. 中大规模集群(十个以上节点),应考虑单独的角色充当。特别并发查询量大,查询的合并量大,可以增加独立的协调节点。角色分开的好处是分工分开,不互影响。如不会因协调角色负载过高而影响数据节点的能力。

如何避免脑裂问题

脑裂问题:一个集群中只有一个A主节点,A主节点因为需要处理的东西太多或者网络过于繁忙,从而导致其他从节点ping不通A主节点,这样其他从节点就会认为A主节点不可用了,就会重新选出一个新的主节点B。过了一会A主节点恢复正常了,这样就出现了两个主节点,导致一部分数据来源于A主节点,另外一部分数据来源于B主节点,出现数据不一致问题,这就是脑裂。

尽量避免脑裂,需要添加最小数量的主节点配置:discovery.zen.minimum_master_nodes: (有master资格节点数/2) + 1

这个参数控制的是,选举主节点时需要看到最少多少个具有master资格的活节点,才能进行选举。官方的推荐值是(N/2)+1,其中N是具有master资格的节点的数量。

** 常用做法 **(中大规模集群):

    1. Master 和 dataNode 角色分开,配置奇数个master
    1. 单播发现机制,配置master资格节点:
      1
      2
      discovery.zen.ping.multicast.enabled: false —— 关闭多播发现机制,默认是关闭的
      discovery.zen.ping.unicast.hosts: ["master1", "master2", "master3"] —— 配置单播发现的主节点ip地址,其他从节点要加入进来,就得去询问单播发现机制里面配置的主节点我要加入到集群里面了,主节点同意以后才能加入,然后主节点再通知集群中的其他节点有新节点加入
    1. 配置选举发现数,及延长ping master的等待时长
      1
      2
      discovery.zen.ping_timeout: 30(默认值是3秒)——其他节点ping主节点多久时间没有响应就认为主节点不可用了
      discovery.zen.minimum_master_nodes: 2 —— 选举主节点时需要看到最少多少个具有master资格的活节点,才能进行选举

索引应该设置多少个分片

说明:分片数指定后不可变,除非重索引。

思考:

分片对应的存储实体是什么?存储的实体是索引

分片是不是越多越好?  不是

分片多有什么影响?  分片多浪费存储空间、占用资源、影响性能

  • 分片过多的影响
    1
    2
    3
    每个分片本质上就是一个Lucene索引, 因此会消耗相应的文件句柄, 内存和CPU资源。
    每个搜索请求会调度到索引的每个分片中. 如果分片分散在不同的节点倒是问题不太. 但当分片开始竞争相同的硬件资源时, 性能便会逐步下降。
    ES使用词频统计来计算相关性. 当然这些统计也会分配到各个分片上. 如果在大量分片上只维护了很少的数据, 则将导致最终的文档相关性较差。
  • 分片设置的可参考原则
    1
    2
    3
    ElasticSearch推荐的最大JVM堆空间是30~32G, 所以把你的分片最大容量限制为30GB, 然后再对分片数量做合理估算. 例如, 你认为你的数据能达到200GB, 推荐你最多分配7到8个分片。
    在开始阶段, 一个好的方案是根据你的节点数量按照1.5~3倍的原则来创建分片. 例如,如果你有3个节点, 则推荐你创建的分片数最多不超过9(3x3)个。当性能下降时,增加节点,ES会平衡分片的放置。
    对于基于日期的索引需求, 并且对索引数据的搜索场景非常少. 也许这些索引量将达到成百上千, 但每个索引的数据量只有1GB甚至更小. 对于这种类似场景, 建议只需要为索引分配1个分片。如日志管理就是一个日期的索引需求,日期索引会很多,但每个索引存放的日志数据量就很少。

分片应该设置几个副本

说明:副本数是可以随时调整的!

思考:

副本的用途是什么?备份数据保证高可用数据不丢失,高并发的时候参与数据查询

针对它的用途,我们该如何设置它的副本数? 一般一个分片有1-2个副本即可保证高可用

集群规模没变的情况下副本过多会有什么影响?  副本多浪费存储空间、占用资源、影响性能

** 副本设置基本原则**

为保证高可用,副本数设置为2即可。要求集群至少要有3个节点,来分开存放主分片、副本。如发现并发量大时,查询性能会下降,可增加副本数,来提升并发查询能力。

注意:新增副本时主节点会自动协调,然后拷贝数据到新增的副本节点

集群搭建

利用docker容器搭建伪集群

在Linux中创建目录,并且配置好:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|-- node1
| |-- config
| | `-- es1.yml
| |-- data
| `-- plugins
|-- node2
| |-- config
| | `-- es1.yml
| |-- data
| `-- plugins
`-- node3
|-- config
| `-- es1.yml
|-- data
`-- plugins

目录文件: 是用来挂载用的,同步配置文件。容器的和外部的同步。

开启防火墙(9300、9301、9302):firewall-cmd –add-port=9301/tcp

分别配置好配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
cluster.name: elasticsearch-cluster
node.name: es-node3
network.bind_host: 0.0.0.0
network.publish_host: 172.17.0.13
http.port: 9202
transport.tcp.port: 9302
http.cors.enabled: true
http.cors.allow-origin: "*"
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["172.17.0.11:9300","172.17.0.12:9301","172.17.0.13:9302"]
discovery.zen.minimum_master_nodes: 2

discovery.zen.minimum_master_nodes: 1 master节点有1个 # discovery.zen.minimum_master_nodes—节点总数/2+1

说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
cluster.name:用于唯一标识一个集群,默认值是:elasticsearch。
node.name:节点名,默认随机指定一个name列表中名字。集群中node名字不能重复

index.number_of_shards: 默认的配置是把索引分为5个分片
index.number_of_replicas:设置每个index的默认的冗余备份的分片数,默认是1

通过 index.number_of_shards,index.number_of_replicas默认设置索引将分为5个分片,每个分片1个副本,共10个结点。

bootstrap.memory_lock: true 当JVM做分页切换(swapping)时,ElasticSearch执行的效率会降低,推荐把ES_MIN_MEM和ES_MAX_MEM两个环境变量设置成同一个值,并且保证机器有足够的物理内存分配给ES,同时允许ElasticSearch进程锁住内存

network.bind_host: 设置可以访问的ip,可以是ipv4或ipv6的,默认为0.0.0.0,这里全部设置通过

network.publish_host:设置其它结点和该结点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址

同时设置bind_host和publish_host两个参数可以替换成network.host
network.bind_host: 172.17.0.11
network.publish_host: 172.17.0.11
=>network.host: 172.17.0.11

http.port:设置对外服务的http端口,默认为9200

transport.tcp.port: 设置节点之间交互的tcp端口,默认是9300

http.cors.enabled: 是否允许跨域REST请求

http.cors.allow-origin: 允许 REST 请求来自何处

node.master: true 配置该结点有资格被选举为主结点(候选主结点),用于处理请求和管理集群,false为不具有选举的资格。

node.data: true 配置该结点是数据结点,用于保存数据,执行数据相关的操作(CRUD,Aggregation);

discovery.zen.minimum_master_nodes:
自动发现master节点的最小数,如果这个集群中配置进来的master节点少于这个数目,es的日志会一直报master节点数目不足,默认为1。
为了避免脑裂,个数请遵从该公式 => (totalnumber of master-eligible nodes / 2 + 1)。
脑裂是指在主备切换时,由于切换不彻底或其他原因,导致客户端和Slave误以为出现两个active master,最终使得整个集群处于混乱状态。

discovery.zen.ping.unicast.hosts: 集群个节点IP地址,也可以使用es-node等名称,需要各节点能够解析

分别启动:

1
2
3
4
5
docker run -d -p 9200:9200 -p 9300:9300 -v /root/es-cluster/node1/config/es1.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /root/es-cluster/node1/plugins:/usr/share/elasticsearch/plugins -v /root/es-cluster/node1/data:/usr/share/elasticsearch/data -e ES_JAVA_OPTS="-Xms512m -Xmx512m" --name es-node1 bdaab402b220

或:

docker run -d -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -p 9200:9200 -p 9300:9300 --mount type=bind,source=/root/es-cluster/node1/config/es1.yml,target=/usr/share/elasticsearch/config/elasticsearch.yml --mount type=bind,source=/root/es-cluster/node1/plugins,target=/usr/share/elasticsearch/plugins --mount type=bind,source=/root/es-cluster/node1/data,target=/usr/share/elasticsearch/data --name es-node1 bdaab402b220

docker run -d -e ES_JAVA_OPTS=”-Xms512m -Xmx512m” -p 9201:9201 -p 9301:9301 -v /root/es-cluster/node2/config/es1.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /root/es-cluster/node2/plugins:/usr/share/elasticsearch/plugins -v /root/es-cluster/node2/data:/usr/share/elasticsearch/data –name es-node2 bdaab402b220

docker run -d -e ES_JAVA_OPTS=”-Xms512m -Xmx512m” -p 9202:9202 -p 9302:9302 -v /root/es-cluster/node3/config/es1.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /root/es-cluster/node3/plugins:/usr/share/elasticsearch/plugins -v /root/es-cluster/node3/data:/usr/share/elasticsearch/data –name es-node3 bdaab402b220

出现的问题:

1、Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000c5330000, 986513408, 0) failed; error=’Cannot allocate memory’ (errno=12)

解决办法是,运行的时间添加设定每个容器的 ES_JAVA_OPTS=”-Xms256m -Xmx256m”

2、bootstrap checks failed max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]

** 调高JVM线程数限制数量 **

1
2
3
4
5
6
7
在centos窗口中,修改配置sysctl.conf
vim /etc/sysctl.conf

加入如下内容:
vm.max_map_count=262144

启用配置:sysctl -p

3、OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.

增加data权限 ,如果有can not run elasticsearch as root则需要使用切换普通用户操作。;

4、docker WARNING: IPv4 forwarding is disabled

1
2
3
4
在宿主机上面执行:
net.ipv4.ip_forward=1 >> /usr/lib/sysctl.d/00-system.conf
重启network和docker服务
systemctl restart network && systemctl restart docker

5、Caused by: java.io.IOException: No route to host

data文件中的节点数据,需要把示例二data文件下的文件清空。rm -rf ./node/data/

正式集群

  1. 准备3台虚拟机:

  2. 168.152.128 、192.168.152.129、192.168.152.130

  3. 在3台虚拟机里面都安装好elasticsearch
    安装教程参考我之前写的文章的ES的安装和配置部分:

https://www.cnblogs.com/leeSmall/p/9189078.html

  1. 修改3台虚拟机下ES的配置,使得它们组成一个集群
    进入elasticsearch的config目录,修改elasticsearch.yml的配置

3.1. IP访问限制、默认端口修改9200
这里有两个需要提醒下,第一个就是IP访问限制,第二个就是es实例的默认端口号9200。IP访问限制可以限定具体的IP访问服务器,这有一定的安全过滤作用。

#Set the bind address to a specific IP (IPv4 or IPv6):

network.host: 192.168.152.128
如果设置成0.0.0.0则是不限制任何IP访问。一般在生产的服务器可能会限定几台IP,通常用于管理使用。

默认的端口9200在一般情况下也有点风险,可以将默认的端口修改成另外一个,这还有一个原因就是怕开发人员误操作,连接上集群。当然,如果你的公司网络隔离做的很好也无所谓。

#Set a custom port for HTTP:

http.port: 9200
transport.tcp.port: 9300
这里的9300是集群内部通讯使用的端口,这个也可以修改掉。因为连接集群的方式有两种,通过扮演集群node也是可以进入集群的,所以还是安全起见,修改掉默认的端口。

说明:记得修改安装了ES的3台虚拟机(三个节点)的相同配置,要不然节点之间无法建立连接工作,也会报错。

3.2 集群发现IP列表、node、cluster名称
紧接着修改集群节点IP地址,这样可以让集群在规定的几个节点之间工作。elasticsearch,默认是使用自动发现IP机制。就是在当前网段内,只要能被自动感知到的IP就能自动加入到集群中。这有好处也有坏处。好处就是自动化了,当你的es集群需要云化的时候就会非常方便。但是也会带来一些不稳定的情况,如,master的选举问题、数据复制问题。

导致master选举的因素之一就是集群有节点进入。当数据复制发生的时候也会影响集群,因为要做数据平衡复制和冗余。这里面可以独立master集群,剔除master集群的数据节点能力。

固定列表的IP发现有两种配置方式,一种是互相依赖发现,一种是全量发现。各有优势吧,我是使用的依赖发现来做的。这有个很重要的参考标准,就是你的集群扩展速度有多快。因为这有个问题就是,当全量发现的时候,如果是初始化集群会有很大的问题,就是master全局会很长,然后节点之间的启动速度各不一样。所以我采用了靠谱点的依赖发现。

你需要在192.168.152.128的elasticsearch中配置成:

#——————————— Discovery ———————————-

#Pass an initial list of hosts to perform discovery when new node is started:
#The default list of hosts is [“127.0.0.1”, “[::1]”]

discovery.zen.ping.unicast.hosts: [ “192.168.152.129:9300”,”192.168.152.130:9300” ]
让他去发现129,130的机器,以此内推,完成剩下的129和130机器的配置。

然后你需要配置下集群名称,就是你当前节点所在集群的名称,这有助于你规划你的集群。集群中的所有节点的集群名称必须一样,只有集群名称一样才能组成一个逻辑集群。

#———————————- Cluster ———————————–

#Use a descriptive name for your cluster:

cluster.name: mycluster
配置你当前节点的名称

#———————————— Node ————————————

#Use a descriptive name for the node:

node.name: node-1
以此类推,完成另外两个节点的配置。cluster.name的名称必须保持一样。然后分别设置node.name。

说明:

这里搭建的是一个简单的集群,没有做集群节点角色的区分,所以3个节点默认的角色有主节点、数据节点、协调节点

选举ES主节点的逻辑:

选举的大概逻辑,它会根据分片的数据的前后新鲜程度来作为选举的一个重要逻辑。(日志、数据、时间都会作为集群master全局的重要指标)

因为考虑到数据一致性问题,当然是用最新的数据节点作为master,然后进行新数据的复制和刷新其他node。

2、[WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main] org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root

新的版本安全级别 提高了,不允许采用root启动,我们需要添加一个新的用户。

1
2
3
4
5
6
7
1、创建elasticsearch用户组:[root@localhost /]# groupadd elasticsearch
2、创建elasticsearch用户:[root@localhost elasticsearch-6.1.1]# useradd elasticsearch -g elasticsearch -p elasticsearch
3、更改 elasticsearch-6.1.1文件夹下所有文件的所属用户和组分别为elasticsearch、elasticsearch。命令: chown -R elasticsearch.elasticsearch *(chown将指定文件的拥有者,-R代表处理指定目录以及子目录下的所有文件)
4、给elasticsearch用户分配读写“/usr/local/fast/elasticsearch-6.1.1/data”的权限 命令:chown -R elasticsearch:elasticsearch elasticsearch-6.1.1
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536],修改/etc/security/limits.conf,添加如下内容,如果不成功的话可以尝试ulimit -n 65536。
[2]: max number of threads [794] for user [elasticsearch] is too low, increase to at least [4096],修改/etc/security/limits.d/20-nproc.conf和/etc/security/limits.conf。
[3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144],修改/etc/sysctl.conf文件,具体如下。修改完成后,输入sysctl -a 命令。

集群管理

  1. 监控API
    http://localhost:9200/_cat

复制代码
GET /_cat

/_cat/health
/_cat/nodes
/_cat/master
/_cat/indices
/_cat/allocation
/_cat/shards
/_cat/shards/{index}
/_cat/thread_pool
/_cat/segments
/_cat/segments/{index}
复制代码
2. x-pack
为集群提供安全防护、监控、告警、报告等功能的收费组件;
部分免费:https://www.elastic.co/subscriptions
6.3开始已开源,并并入了elasticsearch核心中。

官网安装介绍:

https://www.elastic.co/guide/en/elasticsearch/reference/6.2/installing-xpack-es.html

参考文章:

集群搭建一:https://www.cnblogs.com/wangiqngpei557/p/5967377.html

集群搭建二:https://www.cnblogs.com/jstarseven/p/6803054.html 这一篇文章写得比较详细,同时还总结了搭建过程中遇到的问题,搭建ES集群的话强烈推荐

配置参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
cluster.name: ES	ES集群名称,同一个集群内的所有节点集群名称必须保持一致
node.name: slave2 ES集群内的节点名称,同一个集群内的节点名称要具备唯一性
node.master: true 允许节点是否可以成为一个master节点,ES是默认集群中的第一台机器成为master,如果这台机器停止就会重新选举
node.data: false 允许该节点存储索引数据(默认开启)
path.data: ES是搜索引擎,会创建文档,建立索引,此路径是索引的存放目录.可以指定多个存储位置
path.logs: elasticsearch专门的日志存储位置
bootstrap.memory_lock: true 在ES运行起来后锁定ES所能使用的堆内存大小,锁定内存大小一般为可用内存的一半左右;锁定内存后就不会使用交换分区。如果不打开此项,当系统物理内存空间不足,ES将使用交换分区,ES如果使用交换分区,那么ES的性能将会变得很差
network.host: 0.0.0.0 es的HTTP端口和集群通信端口就会监听在此地址上
network.tcp.no_delay: true 是否启用tcp无延迟,true为启用tcp不延迟,默认为false启用tcp延迟
truenetwork.tcp.keep_alive: true 是否启用TCP保持活动状态,默认为true
network.tcp.reuse_address: true 是否应该重复使用地址。默认true,在Windows机器上默认为false
network.tcp.send_buffer_size: 128mb tcp发送缓冲区大小,默认不设置
network.tcp.receive_buffer_size: 128mb tcp接收缓冲区大小,默认不设置
transport.tcp.port: 9301 设置集群节点通信的TCP端口,默认就是9300
transport.tcp.compress: true 设置是否压缩TCP传输时的数据,默认为false
http.max_content_length: 200mb 设置http请求内容的最大容量,默认是100mb
http.cors.enabled: true 是否开启跨域访问
http.cors.allow-origin: "*" 开启跨域访问后的地址限制,*表示无限制
http.port: 9201 定义ES对外调用的http端口,默认是9200
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"] 在Elasticsearch7.0版本已被移除,配置错误。写入候选主节点的设备地址,来开启服务时就可以被选为主节点。默认主机列表只有127.0.0.1和IPV6的本机回环地址。上面是书写格式,discover意思为发现,zen是判定集群成员的协议,unicast是单播的意思,ES5.0版本之后只支持单播的方式来进行集群间的通信,hosts为主机
discovery.zen.minimum_master_nodes: 2 在Elasticsearch7.0版本已被移除,配置无效,为了避免脑裂,集群的最少节点数量为,集群的总节点数量除以2加一
discovery.zen.fd.ping_timeout: 120s 在Elasticsearch7.0版本已被移除,配置无效。探测超时时间,默认是3秒,我们这里填120秒是为了防止网络不好的时候ES集群发生脑裂现象
discovery.zen.fd.ping_retries: 6 在Elasticsearch7.0版本已被移除,配置无效。探测次数,如果每次探测90秒,连续探测超过六次,则认为节点该节点已脱离集群,默认为3次
discovery.zen.fd.ping_interval: 15s 在Elasticsearch7.0版本已被移除,配置无效。节点每隔15秒向master发送一次心跳,证明自己和master还存活,默认为1秒太频繁
discovery.seed_hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"] Elasticsearch7新增参数,写入候选主节点的设备地址,来开启服务时就可以被选为主节点,由discovery.zen.ping.unicast.hosts:参数改变而来
cluster.initial_master_nodes: ["127.0.0.1:9301","127.0.0.1:9302"] Elasticsearch7新增参数,写入候选主节点的设备地址,来开启服务时就可以被选为主节点
cluster.fault_detection.leader_check.interval: 15s Elasticsearch7新增参数,设置每个节点在选中的主节点的检查之间等待的时间。默认为1秒
discovery.cluster_formation_warning_timeout: 30s Elasticsearch7新增参数,启动后30秒内,如果集群未形成,那么将会记录一条警告信息,警告信息未master not fount开始,默认为10秒
cluster.join.timeout: 30s Elasticsearch7新增参数,节点发送请求加入集群后,在认为请求失败后,再次发送请求的等待时间,默认为60秒
cluster.publish.timeout: 90s Elasticsearch7新增参数,设置主节点等待每个集群状态完全更新后发布到所有节点的时间,默认为30秒
cluster.routing.allocation.cluster_concurrent_rebalance: 32 集群内同时启动的数据任务个数,默认是2个
cluster.routing.allocation.node_concurrent_recoveries: 32 添加或删除节点及负载均衡时并发恢复的线程个数,默认4个
cluster.routing.allocation.node_initial_primaries_recoveries: 32 初始化数据恢复时,并发恢复线程的个数,默认4个