ES 实战如何进行集群规划
Posted 顧棟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES 实战如何进行集群规划相关的知识,希望对你有一定的参考价值。
文章目录
集群规划
集群的规划包含以下几个层面:
- 系统层
- 集群层面
- 节点层面
- 索引层面
- 其他
- 客户端
- 读写
系统层
1. 操作系统
官方团队对64 位系统进行了稳定性测试和系统性兼容,其中除了以下一些版本以外都可以较好的支持:
- CentOS 家族(6、7、8)中,CentOS6 不支持7.9.2 版本捆绑的JDK15+
- Debian 家族(7~10)中, Debian 7 从5.x 版本开始不支持
- Ubuntu 家族(14、16、18)中,Ubuntu 14.04 从7.x 版本开始不支持,但Ubuntu 16,18 都支持7.x 。
- Windows 家族(Windows server 2012/R2、2016、2019)中,只有Windows server 2019 对ES 7.7 之前的版本兼容性有限。
再结合通用云厂商和自建服务器的操作系统选型中,CentOS 7 得到了较好的支持和维护,所以此处我们选择以CentOS 7 作为首选操作系统。
2. 内存、CPU、磁盘
最小1C2G(1核CPU,2G内存),常规PU与内存的比为(1:2~1:4)之间,不同厂家的机器性能存在差异,需要进行压测调整比例。ES的最大/最小堆栈内存建议不超过31G,一般到最大到30G即可。单个节点的数据量不要超过5TB,1TB的索引占用2GB的JVM内存,5TB就需要占用10GB的jvm内存了。在实际使用中也发现,单分片的大小过大,和索引数据的超过一定的量,节点的性能会急剧下降,所以其实内存与存储之间存在一定的比例关系。–待查
不同于内存中的文件,ES 放置在磁盘中的文件的读写是随机的不是顺序的,所以更快的随机读写速度将使ES 提供更快的数据存取速度。
在在线搜索等高频存取的场景中,更建议使用固态硬盘以支持数据的高速读写。
在离线的日志存储等低频读取的场景中,则可以考虑用机械硬盘来节约成本。
3. JDK
根据官网版本支持矩阵来选择。ElaticSearch与JVM支持矩阵
4. 操作系统参数
- 关闭Swap(内存交换区域):禁止将系统缓存中的数据交换到硬盘中。
$. swapoff -a
- 每个进程的VMA(虚拟内存区域)数量:改为655360。
- 修改文件:/etc/sysctl.conf
- 添加/修改一行:vm.max_map_count=655360
- 否则可能会遇到报错:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
- 每个进程可以打开的文件句柄数:改为655360。
- 修改文件:/etc/security/limits.conf
- soft nofile 65535 => * soft nofile 655350
- hard nofile 65535 => * hard nofile 655350
- elasticsearch soft nofile 65535 => elasticsearch soft nofile 655350
- elasticsearch hard nofile 65535 => elasticsearch hard nofile 655350
- 否则可能遇到报错:max file descriptors [65535] for elasticsearch process is too low, increase to at least [65536]
- 开启内存锁定:
- 修改文件:/etc/security/limits.conf
- soft memlock 65535 => * soft memlock unlimited
- hard memlock 65535 => * hard memlock unlimited
- elasticsearch soft memlock 65535 => elasticsearch soft memlock unlimited
- elasticsearch hard memlock 65535 => elasticsearch hard memlock unlimited
- 否则可能在开启了内存锁定时(bootstrap.memory_lock: true)遇到报错: memory locking requested for elasticsearch process but memory is not locked
- 为ES创建用户:
- useradd -m elasticsearch
5. 生产模式启动强制校验项
配置文件 | 说明 | 配置项 | 默认值 | 期望值 |
---|---|---|---|---|
conf/jvm.options | 最大/ 小堆内存 | -Xmx -Xms | -Xmx 1g -Xms1g | 部署节点可用内存的一半,最大30G |
elasticsearch.yml | 内存锁定 | bootstrap.memory_lock | NA | true |
/etc/sysctl.conf | 虚拟内存区域 | vm.max_map_count | 65530 | > 262144 |
/etc/security/limits.conf | 文件可打开句柄 | soft/hard nofile | 65536 | 66350 |
/etc/security/limits.conf | 内存锁定 | soft/hard memlock | NA | unlimited |
/etc/security/limits.conf | 虚拟内存 | soft/hard as | NA | unlimited |
/etc/security/limits.conf | 最大进程数 | soft/hard nproc | NA | 10240 |
/etc/security/limits.conf | 最大文件空间 | soft/hard fsize | NA | unlimited |
6. 配置Linux OOM Killer
$sudo echo -17 > /proc/1849/oom_score_adj
1849是es的process号
7. TCP参数修改
net.ipv4.tcp_syn_retries
默认为6 参考值2,主机作为客户端,TCP三次握手时,第一步,发送SYN报文的重试次数。
net.ipv4.tcp_synack_retries
默认为6 参考值2,主机作为服务端,TCP三次握手时,第二步,想客户端发送SYN+ACK报文的重试次数。
net.ipv4.tcp_timetamps
默认为1 参考值1,是否开启时间戳。1开启 0关闭
net.ipv4.tcp_tw_reuse
默认为0 参考值1,该参数只有在开启timetamps时才有效。是否允许将处于TIME_WAIT状态下的socket用于新的TCP连接。
net.ipv4.tcp_tw_recycle
默认为0 参考值0,该参数只有在开启timetamps时才有效。是否开启TIME_WAIT下的socket的快速回收。建议关闭。
net.core.somaxconn
默认为128 参考值2048,定义了系统每一个端口上最大的监听队列长度。队列的实际长度是min(backlog,somaxconn)。backlog是listen调用传入的第二个参数。ES集群如果节点数比较多,在full restart的时候 瞬间会建立大量的连接,是需要是适当放大这个值。
net.ipv4.tcp_max_syn_backlog
默认为128 参考值8192,内核在服务端建立两个队列
- 已完成三次握手,连接建立完成,等待accept队列
- 三次握手过程执行到第二步骤,等待客户端返回ACK,这些未完成的连接单独在一个队列,由tcp_max_syn_backlog定义队列大小。
net.ipv4.tcp_max_tw_buckets
默认为4096 参考值180000,定义系统保持TIME_WAIT状态的socket的最大数量。超过这个数,TIME_WAIT状态的socket将会被立即清除并输出告警信息。TIME_WAIT状态是有客户端产生的,如果想根除,那就让客户端关闭这些连接。
ES Node之间的通信呢,一个Node即有客户端又有服务端吧,那怎么清除,直接重启?
net.ipv4.tcp_max_orphans
默认为4096 参考值262144,定义孤儿socket的数量,超过这个值,这些连接江湖立即reset
,并输出告警。为了应对高负载可以提高该值。
孤儿嵌套字:未附加到任何用户文件句柄的嵌套字
同时还需要考虑 TCP的接收窗口(RWND)和TCP的拥塞窗口(CWND)
8. vm相关
# 当内存中的脏数据超过这个百分比后,系统采用异步的方式刷盘。默认值 10
vm.dirty.background_ratio
# 当内存中的脏数据超过这个百分比后,系统采用同步方式刷盘。默认值 30
vm.dirty_ratio
# 当内存中的脏数据超过这个字节数之后,系统采用同步方式刷盘。
vm.dirty.background_bytes
# 当内存中的脏数据超过这个字节数后,系统采用同步方式刷盘。
vm.dirty_bytes
# 定义脏数据过期时间,超过这个时间后,系统采用异步的方式刷盘,默认值 3000,单位百分之1秒,也就是30s。
vm.dirty_expire_centisecs
# 定义系统周期性启动线程检查是否需要刷盘的间隔时间,默认500,单位百分之1秒,5s。
vm.dirty_writeback_centisecs
查询脏页情况,绝大部分的情况是32-bit
使用4KB
页大小,64-bit
使用8KB
页大小。
cat /proc/vmstat | egrep "dirty|writeback"
9. 禁用透明大页(Transparent Hugepages)
默认开启。查询状态
cat /sys/kernel/mm/transparent_hugepage/enabled
临时禁用
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
集群层
1. 影响因素
- 数据总量,日变化量
- 查询类型 TPS QPS
- SLA级别
- 节点数
- 分片大小与分片数
- ···
2. 部署架构
最小化部署使用3个Master角色节点和3个Data角色节点,尽量将集群节点角色单一化,3个Master都使用单独的进程,甚至单独的机器进行部署。3个数据节点在实践下来 可以最小使用(2C 4G 200G) 和最大支持(15C 30G 20TB)的配置。当数据量越来越多的时候,GC加剧,性能也就下降了。
独立部署Master节点,会加快主切换的进程。同时由于Master不存数据的话,单纯的Master节点宕机,不会产生未分配的分片,集群的状态迅速Green。
如果在部署架构的存在节点作为coordination角色,则需要较大的内存和CPU。Ingest角色的节点需要较大的CPU。和master一样 这样角色的节点对存储的要求不高。
节点层
Elasticsearch支持多种节点角色,一个节点可以支持多个角色,也可以支持一种角色。
节点角色说明:
-
Master,管理节点,管理集群元数据信息,集群节点信息,集群索引元数据信息;
-
Data,数据节点,存储实际数据,提供初步联合查询,初步聚合查询,也可以作为协调节点;
-
Ingest,数据处理节点,类似ETL处理;
-
Coordinate,协调节点,数据查询协调、数据写入协调;
-
Machine Learning,机器学习节点,模型训练与模型预测。
- 不要轻易的调整ES相关线程池的大小。一般都够用。
- 为系统Cache留下一半的物理内存。50%作为堆内存,50%物理内存给Lucene中。
索引层
索引在使用时,由于之后的版本要取消type的概念,都使用一个或者默认的type。
详细见:索引规划文档。
其他
客户端
- 建议使用REST客户端,降低兼容问题带来的影响。也减少由于ES升级带来的工作量。
- 在创建ES客户端的时候 Transport客户端有一个
client.transport.sniff
属性,默认是false
,如果设置为true
,会自动识别出集群索引的节点,然后在发送请求的时候会进行节点的轮询,通过这样的方式进行节点间任务的均衡。 - 使用rest客户端时,只会轮询在创建时,传入的连接地址列表中的节点。
- 连接地址尽量使用拥有Data角色和Coordinate角色的节点,不要去使用Master角色的地点。
- 注意:使用bulk请求的时候,如果遇到429的返回状态码。说明此次bulk里面的请求部分成功、部分失败,客户端需要对数据进行处理,对失败的数据进行重试。
读写
- 避免查询返回数据量巨大的结果集,善用Srcoll API。
- 不要写入过大的文档,一般一个文档到达MB级别已经算大的了。http.max_context_length的默认值为100MB。Lucene有2GB的限制。
- 了解自己的查询计划,使用 Profile API 调试自己的查询语句。
参考
- 《ElasticSearch源码解析与优化实践》 张超
- 《Elastic Stack实战手册(早鸟版)》 阿里云
以上是关于ES 实战如何进行集群规划的主要内容,如果未能解决你的问题,请参考以下文章
elasticsearch系列八:ES 集群管理(集群规划集群搭建集群管理)