35

ES优化看这10条就够了 - 简书

 3 years ago
source link: https://www.jianshu.com/p/883325b7bbda?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ES优化最佳实践

0.6392020.07.24 18:14:32字数 910阅读 1,116

11条优化带你的ES飞起来

1、bool 查询的 filter 筛选

众所周知,ES中filter是不参与相关性评分的,所以查询子句可以被系统进行缓存,性能要高于普通的query查询。
bool查询中支持4种子句,分别是filter、must、must_not、should,其中filter和must_not属于过滤器,过滤器查询先于其它查询执行。
另外在function_score、constant_score中也可以使用filter子句进行查询缓存。

2、设置indices.memory.index_buffer_size

indices.memory.index_buffer_size默认是jvm大小的10% ,将该值调大到20%,经常查询的索引分片数据会被缓存,当该值足够大时缓存的数据就会更多,查询就会更快。

3、segment merge

  • 增加 Index Refresh 间隔,目的是减少 Segment Merge 的次数,建议设置为30s-90s
  • 定期将只读或写少的索引进行segment合并,降低segment数量对搜索性能提升帮组很大,合并过程中将only_expunge_deletes设置为true意思是将标记为删除的数据清除掉。
curl -XPOST "http://host/visitor/_forcemerge?only_expunge_deletes=true&max_num_segments=1&flush=true"

4、SearchType

SearchType默认是QUERY_THEN_FETCH,可在查询时指定为dfs_query_then_fetch,这样协调节点只需要请求一次数据节点就可以完成请求处理了。


QUERY_THEN_FETCH:ES 默认的搜索方式。第一步,先向所有的分片发请求,各分片只返回文档的相似度得分和文档的 ID,然后协调节点按照各分片返回的分数进行重新排序和排名,再取出需要返回给客户端的 Size 个文档 ID。
第 2 步,在相关的分片中取出文档的详细信息并返回给用户。

QUERY_AND_FETCH:协调节点向所有分片发送查询请求,各分片将文档的相似度得分和文档的详细信息一起返回。
然后,协调节点进行重新排序,再取出需要返回给客户端的数据,将其返回给客户端。由于只需要在分片中查询一次,所以性能是最好的。

DFS_QUERY_THEN_FETCH:与 QUERY_THEN_FETCH 类似,但它包含一个额外的阶段:在初始查询中执行全局的词频计算,以使得更精确地打分,从而让查询结果更相关。
QUERY_THEN_FETCH 使用的是分片内部的词频信息,而 DFS_QUERY_THEN_FETCH 使用访问公共的词频信息,所以相比 QUERY_THEN_FETCH 性能更低。

DFS_QUERY_AND_FETCH:与 QUERY_AND_FETCH 类似,不过使用的是全局的词频。

/_search?preference=abcd&search_type=dfs_query_then_fetch
#preference 可以确保字符串标识相同时,每次请求会发送到相同的分片执行

5、预排序 IndexSorting

ES 6.x之后新增预排序功能,即索引在创建之前可以指定数据写入后的排序方式,当query时指定的排序方式和预排序逻辑一致时将能够很快获得排序结果,需要注意的是 查询时不能开启total值

{
  "settings": {
    "index": {
      "sort.field": [ "username", "date" ], 
      "sort.order": [ "asc", "desc" ]       
    }
  },
  "mappings": {
    "properties": {
      "username": {
        "type": "keyword",
        "doc_values": true
      },
      "date": {
        "type": "date"
      }
    }
  }
}
{
  "size": 10,
  "sort": [ 
      { "username": "asc" },
      { "date": "desc" }
  ],
  "track_total_hits": false
}

有条件的尽量使用SSD盘,或者挂载多块盘提升io性能,以下是不同磁盘在并发场景下的性能表现:

image.png

7、设置独立的聚合节点

在有聚合分析场景的业务需要单独指定高配服务器用于聚合查询,与现有点查服务进行隔离; 一般要求CPU在16核以上

# 查询聚合节点配置(conf/elasticsearch.yml):
node.master:false
node.data:false
node.ingest:false

8、查询中断

如果不需要精确统计查询命中记录条数,可以配 teminate_after 指定每个 shard 最多匹配 N 条记录后返回,以及设置查询超时时间 timeout 使得请求提前结束

{ 
    "timeout": "10s",
    "terminate_after": 1000,
    "query": {
        
    }
}

9、调整聚合方式

默认深度优先聚合改为广度优先聚合。

"collect_mode" : "breadth_first"

  • depth_first 直接进行子聚合的计算

  • breadth_first 先计算出当前聚合的结果,针对这个结果在对子聚合进行计算。

10、索引冷热分离

一般应用在操作时序日志的场景, 通过定义模板动态生成索引,如将超出3个月的索引通过定时任务归档到cold组 ,具体操作如下:
1、将data node划分为冷热数据节点

# cat elasticsearch.yml    // 配置文件设置tag区分
node.attr.tag: cold/hot   

# bin/elasticsearch -d -Enode.attr.box_type=hot  //启动设置

2、根据模板按月生成索引,格式如 visitor_2019-01

  
#构建索引模板,滚动新增的索引将按照模板进行创建
curl -X PUT "localhost:9200/_template/visitor" -H 'Content-Type: application/json' -d'
{
  "index_patterns": ["visitor_*"], 
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1,
    "index.routing.allocation.include.tag" : "hot"
  },
 "mappings": {}
}
' 

3、归档历史数据到cold节点

curl -X PUT "${es}/${i}/_settings" -H 'Content-Type: application/json' -d'{
        "number_of_replicas": 0,
        "index.routing.allocation.include.tag": "cold"
     }'

11、异步搜索

ES最近发布的几个版本无论是检索过滤,还是聚合分析,在性能上都有明显的提升和改进,亿级数据分组聚合秒出,对于再大的数据还可以使用_async_search查询,这是7.7版本引入的异步交互查询。
如果执行语句超过1s会返回一个执行Id,客户端根据执行Id可获取剩下的执行结果:

POST uplog_view_202008*/_async_search?wait_for_completion_timeout=1000ms
{
  "size":0,
   
  "aggs": {
    "sale_date": {
      "terms": {
        "field": "u_i" ,
        "size": 300
      }
    }
  }
}
GET _async_search/FjRmemhPOFl1U1BDRzN6TjVnZkdsMWcgdmZmbUY1c2hRck8xWXNUYmF4UEppUToxMDMxNTk5NDA=

其它配置说明

cluster.name:elasticsearch:配置 ES 的集群名称,默认值是 ES,建议改成与所存数据相关的名称,ES 会自动发现在同一网段下的集群名称相同的节点。

node.nam:"node1":集群中的节点名,在同一个集群中不能重复。节点的名称一旦设置,就不能再改变了。当然,也可以设置成服务器的主机名称,例如 node.name:${HOSTNAME}。

noed.master:true:指定该节点是否有资格被选举成为 Master 节点,默认是 True,如果被设置为 True,则只是有资格成为 Master 节点,具体能否成为 Master 节点,需要通过选举产生。

node.data:true:指定该节点是否存储索引数据,默认为 True。数据的增、删、改、查都是在 Data 节点完成的。

index.number_of_shards:5:设置都索引分片个数,默认是 5 片。也可以在创建索引时设置该值,具体设置为多大都值要根据数据量的大小来定。如果数据量不大,则设置成 1 时效率最高。

index.number_of_replicas:1:设置默认的索引副本个数,默认为 1 个。副本数越多,集群的可用性越好,但是写索引时需要同步的数据越多。

path.conf:/path/to/conf:设置配置文件的存储路径,默认是 ES 目录下的 Conf 文件夹。建议使用默认值。

path.data:/path/to/data1,/path/to/data2:设置索引数据多存储路径,默认是 ES 根目录下的 Data 文件夹。切记不要使用默认值,因为若 ES 进行了升级,则有可能数据全部丢失。

可以用半角逗号隔开设置的多个存储路径,在多硬盘的服务器上设置多个存储路径是很有必要的。

path.logs:/path/to/logs:设置日志文件的存储路径,默认是 ES 根目录下的 Logs,建议修改到其他地方。

path.plugins:/path/to/plugins:设置第三方插件的存放路径,默认是 ES 根目录下的 Plugins 文件夹。

bootstrap.mlockall:true:设置为 True 时可锁住内存。因为当 JVM 开始 Swap 时,ES 的效率会降低,所以要保证它不 Swap。

network.bind_host:192.168.0.1:设置本节点绑定的 IP 地址,IP 地址类型是 IPv4 或 IPv6,默认为 0.0.0.0。

network.publish_host:192.168.0.1:设置其他节点和该节点交互的 IP 地址,如果不设置,则会进行自我判断。

network.host:192.168.0.1:用于同时设置 bind_host 和 publish_host 这两个参数。

http.port:9200:设置对外服务的 HTTP 端口,默认为 9200。ES 的节点需要配置两个端口号,一个对外提供服务的端口号,一个是集群内部使用的端口号。

http.port 设置的是对外提供服务的端口号。注意,如果在一个服务器上配置多个节点,则切记对端口号进行区分。

transport.tcp.port:9300:设置集群内部的节点间交互的 TCP 端口,默认是 9300。注意,如果在一个服务器配置多个节点,则切记对端口号进行区分。

transport.tcp.compress:true:设置在节点间传输数据时是否压缩,默认为 False,不压缩。

index.merge.scheduler.max_thread_count:1    #索引merge最大线程数

index.translog.durability:async             #这个可以异步写硬盘,增大写的速度

index.translog.sync_interval:120s           #translog间隔时间

thread_pool.bulk.size:20                    #写入线程个数 由于我们查询线程都是在代码里设定好的,我这里只调节了写入的线程数

thread_pool.bulk.queue_size:1000            #写入线程队列大小

index.refresh_interval:300s                 #index刷新间隔

discovery.zen.minimum_master_nodes:1:设置在选举 Master 节点时需要参与的最少的候选主节点数,默认为 1。如果使用默认值,则当网络不稳定时有可能会出现脑裂。

合理的数值为(master_eligible_nodes/2)+1,其中 master_eligible_nodes 表示集群中的候选主节点数。

discovery.zen.ping.timeout:3s:设置在集群中自动发现其他节点时 Ping 连接的超时时间,默认为 3 秒。

在较差的网络环境下需要设置得大一点,防止因误判该节点的存活状态而导致分片的转移。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK