ElasticSearch管理
发现模块(discovery)
发现模块有两个作用:
选主节点和发现集群的新节点。
发现模块配置
发现模块可以有多种实现,Zen为默认的实现,它默认使用组播来发现节点。该方式虽然方便,但是在生产环境下可能也会带来一些问题:
1. 可能会有意外节点的加入
2. 组播会产生大量不必要的通
处于以上问题,Zen允许使用单播模式。当使用单播时,集群外的节点会发送一个Ping到所有配置中指定的地址。通过该种方式,其通知集群中的所有节点,最后的结果是要么加入一个集群,要么组件一个新的集群。
主节点和数据节点配置
每个集群在给定的时间内都只会有一个活动的主节点。如果集群中有多个主节点,那么当原来的主节点宕机或者从集群中删除,可以从中选择新的活动主节点。
配置只持有数据的节点
node.master:false
node.data: true
配置只作为主节点的节点
node.master: true
node.data: false
配置只处理查询请求的节点
node.master:false
node.data: false
主节点选举配置
为了降低脑裂出现的概率,ES提供了discovery.zen.minium_master_nodes参数来定义了“想要组件集群至少需要的候选主节点(node.master=true的节点)数量”,该值最好为node_size/2 + 1
在ES集群中,主节点是唯一可以改变集群状态的节点,当它每次处理完一个状态更新请求,都会现在本地更新,然后发送给其他的节点,发送后会在一个指定的时间内等待其他节点的响应,对于一个繁忙的集群,可能需要增加主节点的等待时间(discovery.zen.publish_timeout)
故障检测
ES在运行的过程中会运行两个检测进程:
1. 主节点发送Ping请求到其他节点,检测其余节点的情况
2. 其他节点发送Ping到主节点,检测主节点是否可用
设置 | 描述 |
discovery.zen.fd.ping_interval | 节点多久向目标节点发送一次ping请求,默认为1s |
discovery.zen.fd.ping_timeout | 节点接到ping响应前最大等待时间,默认为30s |
discovery.zen.fd.ping_retries | 节点被认为不可用前的重试次数,默认为3次 |
网关模块(Gateway)
集群建立后,就开始了恢复的操作,在恢复的过程中,ES从网关(gateway:负责存储ES集群正常运行所有数据的组件)读取元数据和索引,并准备需要使用的分片。主分片恢复完成后,ES就可以对外提供服务了,如果还有副本则继续对副本进行恢复。
gateway模块用于存储es集群的元数据信息。这部分信息主要包括所有的索引连同索引设置和显式的mapping信息。集群元数据的每一次改变(比如增加删除索引等),这些信息都要通过gateway模块进行持久化。当集群第一次启动的时候,这些信息就会从gateway模块中读出并应用。
- gateway.recovery_after_nodes:集群启动恢复进程需要多少个节点启动(包括master 和 data)
- gateway.recovery_after_data_nodes:集群启动恢复进程需要多少个数据节点启动
- gateway.recovery_after_master_nodes:集群启动恢复进程需要多少个master节点启动
- gateway.recovery_after_time:在recovery_after_*_nodes个节点启动后,需要等到多长时间,再启动集群恢复进程。
- gateway.expected_nodes:期望多少个节点(包括master和data)进入集群后,启动恢复。一旦满足,gateway.recovery_after_time参数将忽略。
- gateway.expected_data_nodes:期望多少个数据节点进入集群后,启动恢复。
- gateway.expected_master_nodes:期望多少个master节点进入集群后,启动恢复。
假设有6个节点,4个数据节点,2个主节点。假设希望4个数据节点加入后延迟3分钟开始或者当6个节点在线时会立刻启动。我们的配置就是:
gateway.recover_after_data_nodes: 4
gateway.recover_after_time: 3m
gateway.expected_nodes: 6
恢复过程中的底层配置
- indices.recovery.concurrent_streams: 在从数据源恢复一个分片时可以同时打开的流的数量,默认为3.
- indices.recovery.max_types_per_sec: 在恢复分片时每秒可以传输的最大数据量,默认为20MB。
- indices.recovery.compress: 恢复过程在传输数据时是否压缩数据,默认为true.
- indices.recovery.file_chunk_size: 从源分片拷贝数据时数据块的大小,默认为512KB,当开启了压缩选项时数据块会被压缩。
- indices.recovery.translog_ops: 恢复过程的一次请求里在分片间传输的事务日志的行数,默认1000
- indices.recovery.translog_size: 从源分片拷贝数据时数据块的大小,默认为512KB,当开启了压缩选项时数据块会被压缩。
- 索引级的恢复配置:index.recovery.initial_shards: 可选的配置包括quorum(50%+1的分片存在且可部署)、quorum-1、full、full-1及任意整数值。
性能优化
使用doc values
原因见上期。
热点线程
当集群缓慢,使用大量的CPU资源时,可以使用热点线程API来查看资源都执行在了哪些地方,并可以查看资源消耗的情况。
可以通过已下方式查看热点线程
1. 全局的分析:/_nodes/hot_threads
2. 某个节点的分析:/_nodes/{nodesIds}/hot_threads
部署方案优化
- 当单机容纳不下数据时,考虑多分片
- 当查询性能不足时,考虑多副本。
- 对于一些高性能的服务器,可以考虑一台服务器上部署多个实例
- 通过awarenss的相关配置,阻止分片及其副本部署在同一台机器上。
- 尽量平均分配分片和副本。
- 当集群较大时,考虑设计每个节点的角色。例如 节点只作为查询聚合节点,数据节点,或是主/候选主节点
调整JVM垃圾回收策略
避免内存交换
内存交换是指把内存页写入磁盘的过程,一般发生在物理内存不够或是某些情况下操作系统认为应该发生的时候发生。如果交换了的内存页再次被需要,操作系统会从交换区加载到内存,该过程相对于内存操作而言是是比较慢的。
为了保证ES的高效,在ES中应该避免内存交换的发生,如果达到此目的,需要进行如下配置:
- 设置elasticserach.yml文件中的bootstrap.mlockall=true
- 设置Xms与Xmx的值相同
- 在/etc/security/limits.conf中添加elasticsearch -memlock unlimited
- 在/etc/pam.d/common-session中添加session required pam_limits.so
- 重启es
在高负载场景下使用ES
优化的常规建议
- 选择正确的存储
- 调整索引刷新频率
- 线程池优化:如果你发现ES实例的资源没有100%饱和,但却受到了拒绝执行的错误,此时可能就需要调整ES的线程池了。
可以尝试增加并发的线程数或是增加队列的长度。在调整的过程中需要注意的是,当并发线程数到一个很大的数值时,会产生大量的CPU上下文切换,进而导致性能下降。
大量的队列也可能会出现队列大量积压的情况。 - 调整段合并过程:
一般情况下,如果希望查询的速度更快,就需要更少的段。例如设置index.merge.policy.merge_factory低于默认值10,
会导致更少的段,更低的RAM消耗,更快的查询执行速度但是会出现更慢的索引速度。
如果设置的index.merge.policy.merge_factory较高则会出现相反的情况。另外需要注意的是,默认情况下ES会限制合并的速度在20MB/s.如果使用的是固态硬盘或是I/O效率更高的设备,则可以适当的增加限制的速度。
高查询频率下的优化建议
- 开启分片查询缓存
- 使用doc values优化查询:
Elasticsearch 中的 Doc Values 常被应用到以下场景:
对一个字段进行排序
对一个字段进行聚合
某些过滤,比如地理位置过滤
某些与字段相关的脚本计算
因为文档值被序列化到磁盘,我们可以依靠操作系统的帮助来快速访问。当 working set 远小于节点的可用内存,系统会自动将所有的文档值保存在内存中,使得其读写十分高速; 当其远大于可用内存,操作系统会自动把 Doc Values 加载到系统的页缓存中,从而避免了 jvm 堆内存溢出异常 - 尽可能的使用过滤查询,同时增加过滤器缓存大小
- 尽量使用路由:有着相同路路由值的数据会被保存到相同的分片上,于是在查询时就可以将请求发送到指定的分片上,可以避免合并结果的开销。
- 并行查询(索引做出多分片)
- 控制size和shard_size:size:参数定义最后聚合结果会返回多少组数据给客户端。shard_size有相同的含义,但是定位于分片。上述两个值的增加会让聚合结果更加精准,同事也会消耗过多的资源。降低这两个值会降低精准度,但是会减少资源损耗。
- 字段数据缓存(fielddata)和熔断(circuit breaker):
字段数据缓存主要用于在字段上排序或计算聚合时使用。它将所有字段值加载到内存中,以提供基于快速的基于这些值的操作。
Elasticsearch的字段数据缓存默认是没有大小限制的,尤其是当在很多字段上进行分组和排序的时候。如果这些字段的基础很高,很容易出现OOM.
为此可以采取以下措施:
1. 限制字段缓冲区的大小:indices.fielddata.cache.size
2. 使用断路器( Field data circuit breaker):配置断路器后可以在满足某些条件下抛出异常而不是OOM如果查询大量使用了字段数据缓存(聚合和排序),且频繁的存在内存的问题,可以考虑使用doc_values进行替换。
高索引频率下的优化建议
- 批量索引:如果有大量数据需要索引,可以使用批量索引取代逐个文档的索引。
- 考虑关闭doc values
- 控制文档的字段:文档的大小在一定程度上会影响索引的速度,可以进行控制,如关闭_all字段
- 考虑分片及副本的数量
- 控制refresh和flush
- 修改存储硬盘的类型(SSD最佳)
- 增加节点的索引缓存大小(indices.memory.index_buffer_size,默认使用10%),也将有利于索引吞吐量的增加。
该配置主要是针对节点的,例如节点有20GB的内存,且有10十个分片,则每个分片大约分的200MB的内存作为索引缓存