Elasticsearch
生产环境常用配置和上线清单
Development vs.Production Mode
- 从ES 5开始,支持Development 和Production 两种运行模式
- 开发模式
- 生产模式
Bootstrap Checks
-
一个集群在Production Mode 时,启动时必须通过所有Bootstrap 检测,否则会启动失败
-
Bootstrap Checks 可以分为两类: JVM & Linux Checks。 Linux Checks只针对Linux系统
JVM设定
-
从ES6开始,只支持64位的JVM
- 配置config / jvm. options
-
避免修改默认配置
- 将内存Xms和Xmx设置成一样,避免heap resize 时引发停顿
- Xmx设置不要超过物理内存的50%; 单个节点上,最大内存建议不要超过32 G内存
- https://www. elastic. co/blog/a-heap-of-trouble
- 生产环境,JVM 必须使用Server模式
- 关闭JVM Swapping
集群的API设定
系统设置
-
参照文档 “Setup Elasticsearch > Important System Conf igurat ion”
https://www. elastic. co/ guide/en/elasticsearch/reference/7.1/ system-config. html。 -
Disable Swapping ,Increase file descriptor, 虚拟内存,number of thread
最佳实践:网络
- 单个 集群不要跨数据中心进行部署(不要使用WAN)
- 节点之间的 hops 越少越好
- 如果有多块网卡, 最好将transport和http绑定到不同的网卡,并设置不同的防火墙Rules
- 按需为Coordinating Node或Ingest Node 配置负载均衡
最佳实践:内存设定计算实例
- 内存大小要根据Node需要存储的数据来进行估算
- 搜索类的比例建议: 1:16
- 日志类: 1:48 - 1:96 之间
- 总数据量1 T,设置一个副本=2T总数据量
- 如果搜索类的项目,每个节点31 *16 = 496 G,加上预留空间。所以每个节点最多400 G数据,至少需要5个数据节点
- 如果是日志类项目,每个节点31*50 = 1550 GB, 2个数据节点即可
最佳实践:存储
- 推荐使用 SSD,使用本地存储(Local Disk) 。避免使用SAN NFS / AWS / Azure filesystem
- 可以在本地指定多个 “path. data”,以支持使用多块磁盘
- ES本身提供了很好的HA机制;无需使用RAID 1/5/10
- 可以在Warm节点上使用Spinning Disk, 但是需要关闭Concurrent Merges
- Index. merge. scheduler. max_ thread_ _count: 1
- Trim你的SSD
- https://www. elastic. co/blog/is- -your-e lasticsearch-tr immed
最佳实践:服务器硬件
- 建议 使用中等配置的机器,不建议使用过于强劲的硬件配置
- Medium machine over large machine
- 不建议在一台服务器. 上运行多个节点
集群设置: Throttles 限流
-
为Relocation和Recovery设置限流,避免过多任务对集群产生性能影响
-
Recovery
- Cluster. routing. allocation. node_ concurrent_ recoveries: 2
-
Relocation
- Cluster. routing. al location. cluster_ concurrent rebalance: 2
集群设置:关闭Dynamic Indexes
- 可以考虑关闭动态索引创建的功能
- 或者通过模版设置白名单
集群安全设定
- 为 Elasticsearch和Kibana 配置安全功能
- 打开Authentication & Author izat ion
- 实现索引和和字 段级的安全控制
- 节点间通信加密
- Enable HTTPS
- Audit logs
本节知识点
- Dev Mode v. s Production Mode
- Bootstrap Check
- Best Practices
- Network / Hardware / JVM
集群写性能优化
提高写入性能的方法
-
写性 能优化的目标:增大写吞吐量(Events Per Second) ,越高越好
-
客户端:多线程,批量写
- 可以通过性能 测试,确定最佳文档数量
- 多线程: 需要观察是否有 HTTP 429返回,实现Retry 以及线程数量的自动调节
-
服务器端:单个性能问题,往往是多个因素造成的。需要先分解问题,在单个节点上进行调整并
且结合测试,尽可能压榨硬件资源,以达到最高吞吐量- 使用更好的硬件。 观察CPU / I0 Block
- 线程切换/堆栈状况
服务器端优化写入性能的- -些手段
-
降低IO操作
- 使用ES自动生成的文档Id /一些相关的ES配置,如Refresh Interval
-
降低CPU和存储开销
- 减少不必要分词/避免不需要的doc_ _values /文档的字段尽量保证相同的顺序,可以提高文档的压缩率
-
尽可能做到写入和分片的均衡负载,实现水平扩展
- Shard Filtering / Write Load Balancer
-
调整Bulk 线程池和队列
优化写入性能
- ES的默认设置,已经综合考虑了数据可靠性,搜索的实时性质,写入速度,一般不要盲目修改
- 一切优化,都要基于高质量的数据建模
关闭无关的功能
针对性能的取舍
- 如果需要追求极致的写入速度,可以牺牲数据可靠性及搜索实时性以换取性能
- 牺牲可靠性: 将副本分片设置为0,写入完毕再调整回去.
- 牺牲搜索实时性:增加Refresh Interval 的时间
- 牺牲可靠性: 修改Translog的配置
数据写入的过程
-
Refresh
- 将文档先保存在Index buffer 中,以refresh_ interval 为间隔时间,定期清空buffer, 生成
segment,借助文件系统缓存的特性,先将segment 放在文件系统缓存中,并开放查询,以提升搜索的实时性
- 将文档先保存在Index buffer 中,以refresh_ interval 为间隔时间,定期清空buffer, 生成
-
Translog
- Segment 没有写入磁盘,即便发生了当机,重启后,数据也能恢复,默认配置是每次请求都会落盘
-
Flush
- 删除旧的 translog 文件
- 生成Segment 并写入磁盘/更新commit point 并写入磁盘。 ES自动完成,可优化点不多
Refresh Interval
- 降低Refresh的频率
- 增加refresh_ interval 的数值。默认为ls ,如果设置成-1,会禁止自动refresh
- 避免过于频繁的refresh, 而生成过多的segment 文件
- 但是会降低搜索的实时性
- 增大静态配置参数 indices. memory. index_ buffer size .
- 默认是10%,会 导致自动触发refresh
- 增加refresh_ interval 的数值。默认为ls ,如果设置成-1,会禁止自动refresh
Trans log
- 降低写磁盘的频率, 但是会降低容灾能力
- Index. trans log. durability:默认是request, 每个请求都落盘。设置成async, 异步写入
- Index. translog. sync_ interval 设置为60s,每分钟执行一次 Index. trans log. flush_ threshod_ size: 默认512 mb,可以适当调大。当translog 超过该值,会触发flush
分片设定
- 副本在写 入时设为0,完成后再增加
- 合理设置主分片数, 确保均匀分配在所有数据节点上
- Index. routing. allocation. total_ share_ per_ node: 限定每个索引在每个节点上可分配的主分片数
- 5个节点的集群。 索引有5个主分片,1个副本,应该如何设置?
- (5+5) /5= 2
- 生产环境中要适当调大这个数字,避免有节点下线时,分片无法正常迁移
Bulk,线程池和队列大小
- 客户端
- 单个bulk请求体的数据量不要太大,官方建议大约5-15mb
- 写入端的bulk 请求超时需要足够长,建议60s以上
- 写入端尽量将数据轮询打到不同节点。
- 服务器端
- 索引创建属于计算密集型任务,应该使用固定大小的线程池来配置。来不及处理的放入队列,线程数应该配置成CPU核心数+1,避免过多的上下文切换
- 队列大小可 以适当增加,不要过大,否则占用的内存会成为GC的负担
一个索引设定的例子
demoAPI
DELETE myindex
PUT myindex
{
"settings": {
"index": {
"refresh_interval": "30s",
"number_of_shards": "2"
},
"routing": {
"allocation": {
"total_shards_per_node": "3"
}
},
"translog": {
"sync_interval": "30s",
"durability": "async"
},
"number_of_replicas": 0
},
"mappings": {
"dynamic": false,
"properties": {}
}
}
集群读性能优化
尽量Denormalize 数据
- Elasticsearch ! =关系型数据库.
- 尽可 能Denormalize 数据,从而获取最佳的性能.
- 使用Nested 类型的数据。查询速度会慢几倍
- 使用Parent / Child 关系。查询速度会慢几百倍
数据建模
- 尽量将数据先行计算, 然后保存到Elasticsearch 中。尽量避免查询时的Script 计算
- 尽量使用Filter Context, 利用缓存机制,减少不必要的算分
- 结合 profile, explain API分析慢查询的问题,持续优化数据模型
- 严禁使用*开头通配符Terms 查询
避免查询时脚本
可以在Index 文档时,使用Ingest Pipeline, 计算并写入某个字段
常见的查询性能问题使用Query Context
聚合文档消耗内存
通配符开始的正则表达
- 通配符开头的正则, 性能非常糟糕,需避免使用
优化分片
-
避免 Over Sharing
- 一个查询需要 访问每一个分片,分片过多,会导致不必要的查询开销
-
结合应用场景,控制单个分片的尺寸
- Search:20GB
- Logging: 40GB
-
Force-merge Read-only 索引
- 使用基于时间序列的索引,将只读的索引进行force merge, 减少segment 数量
读性能优化
- 影响查询性能的- -些因素
- 数据模型和索 引配置是否优化
- 数据规模是否过大,通过Filter 减少不必要的数据计算
- 查询语句是否优化
demo API
PUT blogs/_doc/1
{
"title":"elasticsearch"
}
GET blogs/_search
{
"query": {
"bool": {
"must": [
{"match": {
"title": "elasticsearch"
}}
],
"filter": {
"script": {
"script": {
"source": "doc['title.keyword'].value.length()>5"
}
}
}
}
}
}
GET blogs/_search
{
"query": {
"bool": {
"must": [
{"match": {"title": "elasticsearch"}},
{
"range": {
"publish_date": {
"gte": 2017,
"lte": 2019
}
}
}
]
}
}
}