目录
WIndow集群
Linux集群
单点部署
集群部署
ES优化
硬件选择
分片策略
推迟分片分配
路由选择
写入速度优化
批量数据提交
优化存储设备
合理使用合并
减少Refresh的次数
加大Flush设置
减少副本的数量
内存设置
重要配置
创建elasticsearch-cluster文件夹,在内部复制三个elasticsearch服务
修改集群文件目录下每个节点的config/elasticsearch.yml配置文件
节点1的配置信息:
# 集群名称,节点之间要保持一致
cluster.name: my-elasticsearch
# 节点名称,集群内要唯一
node.name: node-1001
# 当前节点是主节点也是数据节点
node.master: true
node.data: true
# 本机ip地址
network.host: loaclhost
# http端口
http.port: 9201
# tcp监听端口
transport.tcp.port: 9301
# 跨域配置
http.cors.enabled: true
http.cors.allow-orrigin: "*"
节点2的配置信息:
# 集群名称,节点之间要保持一致
cluster.name: my-elasticsearch
# 节点名称,集群内要唯一
node.name: node-1002
# 当前节点是主节点也是数据节点
node.master: true
node.data: true
# 本机ip地址
network.host: loaclhost
# http端口
http.port: 9202
# tcp监听端口
transport.tcp.port: 9302
# 查找节点
discovery.seed.hosts: ["localhost:9301"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5
# 跨域配置
http.cors.enabled: true
http.cors.allow-orrigin: "*"
节点3的配置信息:
# 集群名称,节点之间要保持一致
cluster.name: my-elasticsearch
# 节点名称,集群内要唯一
node.name: node-1002
# 当前节点是主节点也是数据节点
node.master: true
node.data: true
# 本机ip地址
network.host: loaclhost
# http端口
http.port: 9202
# tcp监听端口
transport.tcp.port: 9303
# 查找节点
discovery.seed.hosts: ["localhost:9301"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5
# 跨域配置
http.cors.enabled: true
http.cors.allow-orrigin: "*"
安装ES
下载软件解压
Elasticsearch 7.8.0 | Elastic
# 解压
tar -zxvf elasticsearch-7.8.0-linux-x84_64.tar.gz -C /opt/module
# 修名
mv elasticsearch-7.8.0 es
创建用户
因为安全问题,Elasticsearch不允许root用户直接运行,所以要创建新用户,在root用户中心创建新用户
# 新增es用户
useradd es
# 创建密码
passwd es
# 如果错了,可以删除再加
userdel -r es
# 文件夹所有者
chown -R es:es /opt/module/es
修改/opt/module/es/config/elasticsearch.yml文件
cluster.name: elasticsearch
node.name: node-1
network.host:0.0.0.0
http.port:9200
cluster.initial_master_nodes: ["node-1"]
修改/etc/security/limits.conf
# 在文件末尾中加入下面内容
# 每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536
# es是用户名
修改/etc/secutiry/limits.d/20-nproc.conf
# 在文件末尾中加入下面内容
# 每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536
# es是用户名
# 操作系统级别对每个用户创建的进程数的限制
* hard nproc 4096
# 注:* 代表Linux所有用户名称
修改/etc/sysctl.conf
# 在文件中增加下面内容
# 一个进程可以拥有的vma(虚拟内存区域)的数量,默认值为65536
vm.max_map_count=655360
重新加载
sysctl -p
启动ES
# 使用ES用户启动
# 注意:不能用root用户启动
cd /opt/module/es/
# 启动
bin/elasticsearch
# 后台启动
bin/elasticsearch -d
注意
# 如果启动报如下错误
# 修改/usr/local/elasticsearch/config/elasticsearch.keystore文件权限
Exception in thread "main" org.elasticsearch.bootstrap.BootstrapException: java.nio.file.AccessDeniedException: /usr/local/elasticsearch/config/elasticsearch.keystore
Likely root cause: java.nio.file.AccessDeniedException: /usr/local/elasticsearch/config/elasticsearch.keystore
安装ES
下载软件解压
Elasticsearch 7.8.0 | Elastic
# 解压
tar -zxvf elasticsearch-7.8.0-linux-x84_64.tar.gz -C /opt/module
# 修名
mv elasticsearch-7.8.0 es-cluster
将软件分发到其他节点: linux2, linux3
创建用户
因为安全问题,Elasticsearch不允许root用户直接运行,所以要在每个节点创建新用户,在root用户中心创建新用户
# 新增es用户
useradd es
# 创建密码
passwd es
# 如果错了,可以删除再加
userdel -r es
# 文件夹所有者
chown -R es:es /opt/module/es
修改elasticsearch.yml配置文件
每个节点的elasticsearch.yml配置文件,都如下配置,修改下当前节点名称和IP地址即可
# 集群名称
cluster.name: cluster-es
# 当前节点名称,每个节点名称不能重复
node.name: node-1
# 当前节点IP
network.host: 192.168.25.1
# 是不是有资格为主节点
node.master: true
node.data: true
http.port: 9200
# head插件需要打开这两个配置
http.cors.allow-origin: "*"
http.cors.enabled: true
http.max_content_length: 200mb
# es7.x 之后新增的配置, 初始化一个新的集群时需要此配置来选举master
cluster.initial_master_nodes: ["node-1"]
# es7.x 之后新增配置,节点发现
discovery.seed_hosts: ["192.168.25.1:9300","192.168.25.2:9300","192.168.25.3:9300"]
gateway.recover_after_nodes: 2
network.tcp.keep_alive: true
netowrk.tcp.no_delay: true
transport.tcp.compress: true
# 集群内同时启动的数据任务个数,默认是2个
cluster.routing.allocation.cluster_concurrent_rebalance: 16
# 添加或删除节点及负载均衡时并恢复的线程个数,默认是4个
cluster.routing.allocation.node_concurrent_recoveries: 16
# 初始化数据恢复时,并发恢复线程的个数,默认4个
cluster.routing.allocation.node_initial_primaries_recoveries: 16
启动ES
分别在不同节点上启动ES软件
# 注意:不能用root用户启动
cd /opt/module/es-cluster/
# 启动
bin/elasticsearch
# 后台启动
bin/elasticsearch -d
# 注意:如果启动报错可能是启动过程中创建的文件没有权限
# 切换root用户重新设置权限,再重新启动
chown -R es:es /opt/module/es
测试集群
# 浏览器访问
http://192.168.25.1/_cat/nodes
Elasticsearch的基础是Lucene,所有的索引和文档数据是存储在本地磁盘中,具体的路径可在ES的配置文件../config/elasticsearch.yml中配置。
磁盘的现代服务器上通常都是瓶颈。elasticsearch重度使用磁盘,你的磁盘处理的吞吐量越大,你的节点越稳定。
使用SSD,他们比机械硬盘优秀多了
使用RAID条待RAID会提高磁盘I/O,代价显然就是当一块硬盘故障时整个就故障了。不要使用镜像或者奇偶校验RAID应为副本已经提供了这个功能
使用多块硬盘,并允许Elasticsearch通过多个path.data目录配置把数据条带化分配到它们上面
不要使用远程挂载的存储,比如NFS或者SMB/CIFS。这个引入的延迟对性能来说完全背道而驰的
合理设置分片数
分片和副本的设计是为了ES提供了支持分布式和故障转移的特性,但并不意味着分片和副本是可以无限分配的。而且索引的分片完成分配后由于索引的路由机制,我们是不能宠幸3修改分片数的。
一个分片的底层即为一个Lucene索引,会消耗一定文件句柄、内存、以及CPU运作。
每一个搜索请求都需要命中索引中的每一个分片,如果每一个分片都处于不同的节点还好,但是如果多个分片都需要在同一个节点上竞争使用相同的资源就有些糟糕了。
用于计算机相关度的词项统计信息是基于分片的。如果有许多分片,每一个都只有很少的数据会导致很的相关度。
一个业务索引具体需要分配多少分片可能需要架构师和技术人员对业务的增长有个预先的判断,横向扩展应分阶段进行。为下一阶段准备好足够的资源。只有当你进入到下一个阶段,你才有时间思考需要考虑做出哪些改变来达到这个阶段。一般来说,我们遵循一些原则:
控制每个分片占用的硬盘容量不超过ES最大JVM的对空间设置(一般设置不超过32G,参考下文的JVM设置原则),因此,如果索引的总量在500G左右,那分片大小在16个左右即可; 当然最好同时考虑原则2.
考虑一下node数量,一般一个节点有时候就是一台物理机,如果分片数过多,大大超过了节点数,很可能会导致一个节点上存在多个分片,一旦该节点故障,即使保持了1个以上的副本,同样有可能会导致数据丢失,集群无法恢复。所以一般都设置分布数不超过节点数的3倍。
主分片,副本和节点最大数之间数量,我们分配的时候可以参考以下关系:节点数<=主分片数*(副本数+1)
对于节点瞬时中断的问题,默认情况,集群会等待一分钟来查看节点是否会重新加入,如果这个节点在此期间重新加入,重新加入的节点会保持其现有的分片数据,不会触发新的分片分配。这样就可以减少ES在自动平衡可用分片时带来的极大开销。
通过修改参数delayed_timeout,可以延长再均衡的时间,可以全局设置也可以在索引级别进行修改:
PUT /_all/_settings
{
"settings":{
"index.unassigned.node_left.delayed_timeout": "5m"
}
}
当我们查询文档的时候,Elasticsearch如何知道一个文档应该存放到哪个分片中?它其实是通过下面这个公式计算出来:
shard=hash(routing)%number_of_primary_shards
routing默认值是一个文档的Id,也可以采用自定义值,比如用户id.
不带routing查询
在查询的时候因为不知道要查询的数据具体在哪个分片上,所以整个过程分为2个步骤
分发:请求到达协调节点后,协调节点将查询请求分发到每个分片上。
聚合:协调节点搜集到每个分片上查询结果,在将查询的结果进行排序,之后给用户返回结果
带routing查询
查询的时候,可以直接根据routing信息定位到某个分配查询,不需要查询所有分配,经过协调节点排序。
向上面自定义的用户查询,如果routing设置为userid的话,就可以直接查询数据出来,效率提升很多
ES的默认配置,是综合了数据可靠性、写入速度、搜索实时性等因素。实际使用时,我们需要根据公司要求,进行偏向性的优化。
针对于搜素性能要求不高,但是写入要求比较高的场景,我们需要尽可能的使用恰当写优化策略。综合来说,可以考虑以下几个方面来提升写索引的性能:
加大Translog Flush,目的是降低Iops、writeblock.
增加Index Refresh间隔,目的是减少Segment Merge的次数。
调整Bulk线程池和队列。
优化节点间的任务分布。
优化Lucene层的索引建立,目的是降低CPU及IO.
ES提供了Bulk API支持批量操作,当我们有大量的写任务时可以使用Bulk来进行行批量写入。
通用的策略如下:Bulk默认设置批量提交的数据不能超过100M.数据条数一般时根据文档的大小和服务器性能而定的,但是单次批处理的数据大小应从5MB~15MB逐渐增加,当性能没有提升时,把这个数据作为最大值。
ES是一种密集使用磁盘的应用,在段合并的时候会频繁操作磁盘,所以对磁盘要求较高,当磁盘速度提升后,集群的整体性能会大幅度提高。
luncene以段的形式存储数据,当有新的数据写入索引时,Lucene就会自动创建一个新的段。
随着数据量的变化,段的数量会越来越多,消耗的多文件句柄数及CPU就越多,查询效率就会下降。
由于Lucene段合并的计算量庞大,会消耗大量的I/O,所以ES默认采用比较保守的策略,让后台定期进行段合并
Luncene在新增数据时,采用了延迟写入的策略,默认情况下索引的refresh_interval为1秒。
Lucene将待写入的数据先导入到内存中,超过1秒(默认)时就会触发一次Refresh,然后Refresh就会把内存中的数据刷新到操作系统的文件缓存系统中。
如果我们对搜索的实效性要求不高,可以将Refresh周期延迟,例如30秒。这样还可以有效减少刷新次数,但这同时意味着需要消耗更多的Heap内存。
Flush的主要目的时把文件缓存到系统中的段持久化硬盘,当Translog的数据量达到512MB或者30分钟时,会触发一次Flush。
index.translog.flush_threshold_size参数的默认值是512MB,我们进行修改。
增加参数值意味着文件缓存系统中可能需要存储更多的数据,所以我们需要为操作系统的文件缓存系统留下足够的空间。
ES为了保证集群的可用性,提供了Replicas(副本)支持,然而每个副本也会执行分析、索引及可能的合并过程,所以Replicas的数量会严重影响写索引的效率。
当写索引时,需要把写入的数据都同步到副本节点,副本节点越多,写索引的效率就越慢。
如果我们需要大批量进行写入操作,可以先禁止Replica复制,设置index.number_of_replicas:0关闭副本。在写入完成后,Replica修改回正常的状态。
ES默认安装后设置的内存是1GB,对于任何一个现实业务来说,这个设置都太小了。如果是通过解压安装的ES,则在ES安装文件中包含一个jvm.option文件,添加如下命令设置ES的堆大小,Xms表示堆的初始大小,Xmx表示可分配的最大内存,都是1GB.
确保Xmx和Xms的大小是相同的,其目的是为了能够在java垃圾回收机制中清理完堆区后不需要重新分隔计算堆区的大小而浪费资源,可以减轻伸缩堆大小带来的压力。
假设你有一个64G内存的机器,按照正常思维思考,你可能认为把64G内存都给ES比较好,但现实是这样吗,越大越好?虽然内存对ES来说非常重要的,但是答案是否定的!
因为ES堆内存的分配需要满足一下两个原则:
不要超过物理内存%; Lucene的设计目的是把底层OS里的数据缓存到内存中。Lucene的分段是分别存储到单个文件中的,这些文件都是不会变化,所以很利于缓存,同时操作系统也会把这些段文件缓存起来,以便更快的访问。如果我们设置的堆内存过大,Lucene可用的内存将会减少,就会严重影响降低Lucene的全文本查询性能。
堆内存的大小最好不要超过32GB,在java中,所有对象分配在堆上,然后有一个Klass Pointer 指针指向它的类元数据。这个指针在64位的操作系统上为64位,64位的操作系统可以使用更多的内存(2^64)。在32位的系统上为32位,32位的操作系统的最大寻址空间为4GB(2^32).但是64位的指针意味着更大的浪费,因为你的指针本身大了。浪费内存不算,更糟糕的是,更大的指针在主内存和缓存器(例如LLC,L1等)之间移动数据的时候,会占用更多的宽带。
最终我们采用31G设置
-Xms 31g
-Xmx 31g
参数名 | 参数值 | 说明 |
---|---|---|
cluster.name | elasticsearch | 配置ES的集群名称,默认值是ES,建议改成与所存储数据相关的名称,ES会自动发现在同一网段下的集群名称相同的节点 |
node.name | node-1 | 集群中的节点名,在同一个集群中不能重复。节点的名称一旦设置,就不能改变了。当然也可以设置成服务器的主机名称,例如node.name:${HOSTNAME}。 |
node.master | true | 指定该节点是否有资格被选举成为Master节点,默认是True, 如果被设置为True,则只是有资格成为master节点,具体能否成为master节点,需要通过选举产生。 |
node.data | true | 指定该节点是否存储索引数据,默认为true.数据的增、删、改、查都是在Data节点完成的。 |
index.number_of_shards | 1 | 设置都索引分片个数,默认是1片。也可以创建索引时设置该值,具体设置为多大都值要根据数据量的大小来定。如果数据量不大,则设置成1时效率最高。 |
index.number_of_replicas | 1 | 设置默认的索引副本个数,默认为1个。副本数越多,集群的可用性越好,但是写索引时需要同步的数据越多 |
transport.tcp.compress | true | 设置在节点间传输数据时是否压缩,默认为false,不压缩 |
discovery.zen. minimum_master_nodes | 1 | 设置在选举master节点时需要参与最少的候选主节点数,默认为1。如果使用默认值,则当网络不稳定时有可能出现脑裂。合理的数值为(master_eligble_nodes/2)+1,其中master_eligble_nodes表示集群中的侯选主节点数 |
discovery.zen.ping.timeout | 3s | 设置在集群中自动发现其他节点时Ping连接的超时时间。默认为3秒。在较差的网络环境下需要设置得大一点,防止因为误判改节点的存活状态而导致分片的转移。 |