写性能优化的目标:增大写吞吐量(Events Per Second),越高越好
客户端:多线程,批量写
- 可以通过性能测试,确定最佳文档数量
- 多线程:需要观察是否有HTTP 429返回,实现Retry以及线程数量的自动调节
服务端:单个性能的问题,往往是多个因素造成的。需要先分解问题,在单个节点上进行跳转并且结合测试,尽可能压榨硬件资源,以达到最高吞吐量
- 使用更好的硬件。观察CPU /IO Block
- 线程切换/堆栈状况
- 降低IO操作:使用ES自动生成的文档ID/一些相关的ES配置,如:Refresh Interval
- 降低CPU和存储开销:减少不必要的分词/避免不需要的doc_values/文档的字段尽量保证相同的顺序,可以提高文档的压缩率
- 尽可能做到写入和分片的均衡负载,实现水平扩展:shard Fitering/Write Load Balancer
- 调整Bulk线程池和队列
- ES的默认设置,已经综合考虑了数据的可靠性,搜索的实时性,写入速度,一般不需要盲目修改
- 一切优化,都需要级域高质量的数据建模
关闭无关的功能:
- 只需要聚合不需要搜索,index设置成false
- 不需要算分,Norms设置成false
- 不要对字符串使用默认的dynamic mapping。字段数量过多,会对性能产生比较大的影响
设置mapping的时候dynamic可以限制陌生字段,
true:遇到陌生字段,就进行dynamic mapping
false:遇到陌生字段,就忽略
strict:遇到陌生字段,就报错
index_options控制在创建倒排索引时,哪些内容会被添加到倒排索引中。优化这些设置,一定程度可以节约CPU\
关闭_source,减少IO操作;(适合指标型数据)
可以将需要的字段保存在_all中,然后使用IK分词以备查询,其余的字段,则不存储.
{
"mappings": {
"sod_song_ksc": {
"dynamic_templates": [
{
"all_field": {
"mapping": {
"index": "no",
"store": "yes",
"type": "{dynamic_type}",
"include_in_all": false
},
"match": "*"
}
}
],
"_source": {
"enabled": false //关闭_source
},
"_all": {
"enabled": true,
"analyzer": "ik"
},
"properties": {
"SongID": {
"type": "long",
"store": "yes",
"index": "not_analyzed",
"include_in_all": true //保存在_all中
}
}
}
}
}
针对性能的取舍:
Refresh
将文档先保存在Index buffer中,以refresh_interval为间隔时间,定期清空buffer,生成segment,借助文件系统缓存的特性,先将segment放在文件系统缓存中,并开放查询,以提升搜索的实时性
Translog
Segment没有写入磁盘,即便发生了宕机,重启后,数据也能恢复,默认配置是每次请求都会洛盘
Flush
删除旧的translog文件
生成Segment并写入磁盘/更新commit point 并写入磁盘。ES自动完成
Refresh interval:
降低Refresh的频率:
增加refresh_interval的数值。默认为1s,如果设置成-1,会禁止自动refresh
- 避免过于频繁的refresh而生成过多的segment文件
- 但是会降低搜索的实时性
增大静态配置参数
indices.memory.index_buffer_size
- 默认是10%,会导致触发refresh
Translog:
从6.0开始每次写入都会进行translog落盘的操作。
降低写磁盘的频率,但是会降低容灾的能力
- index.translog.durability:默认是request,每个请求都会落盘。设置成async,异步写入
- index.translog.sync_interval设置为60s,每分钟执行一次
- index.translog.flush_threshod_size:默认512Mb,可以适当调大。当translog超过该值,会触发flush
分片设定:
副本在写入时设置为0,完成后再增加
合理设置主分片数,确保均匀分配再所有数据节点上
- index.routing.allocation.total_share_per_node:限定每个索引再每个节点上可分配的主分片数
- 5个节点的集群。索引有5个主分配,1个副本,应该如何设置?
- (5+5)/5 =2 index.routing.allocation.total_share_per_node:2
- 生产环境可适当调大这个数字,避免有节点下线时候分片无法正常迁移
Bulk,线程池和队列大小
客户端
- 单个bulk请求体的数据量不要太大,官方建议5-15mb
- 写入端的bulk请求超时要足够长,建议60s以上
- 写入端尽量将数据轮询打到不同节点
服务端
- 索引创建属于计算密集型任务,应该使用固定大小的线程池来配置。来不及处理的放入队列,线程数配置成cpu核心数+1,避免过多的上下文切换
- 队列大小可以适当增加,不要过大,否则占用的内存会成为GC的负担
一个索引设定的例子:
本文暂时没有评论,来添加一个吧(●'◡'●)