同事:膨胀了?Elasticsearch快就不需要调优了吗?

2020-11-24 11:23:31 浏览数 (1)

转自:jianshu.com/p/883325b7bbda

编辑:可可

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 意思是将标记为删除的数据清除掉。

代码语言:javascript复制
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 默认的搜索方式。

第 1 步,先向所有的分片发请求,各分片只返回文档的相似度得分和文档的 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 值

代码语言:javascript复制
{
  "settings": {
    "index": {
      "sort.field": [ "username", "date" ],
      "sort.order": [ "asc", "desc" ]
    }
  },
  "mappings": {
    "properties": {
      "username": {
        "type": "keyword",
        "doc_values": true
      },
      "date": {
        "type": "date"
      }
    }
  }
}
代码语言:javascript复制
{
  "size": 10,
  "sort": [
      { "username": "asc" },
      { "date": "desc" }
  ],
  "track_total_hits": false
}

6、磁盘

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

7、设置独立的聚合节点

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

代码语言:javascript复制
# 查询聚合节点配置(conf/elasticsearch.yml):
node.master:false
node.data:false
node.ingest:false

8、查询中断

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

代码语言:javascript复制
{
    "timeout": "10s",
    "terminate_after": 1000,
    "query": {

    }
}

9、调整聚合方式

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

"collect_mode" : "breadth_first"

depth_first 直接进行子聚合的计算

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

10、索引冷热分离

一般应用在操作时序日志的场景, 通过定义模板动态生成索引,如将超出 3 个月的索引通过定时任务归档到 cold 组 ,具体操作如下:

1、将 data node 划分为冷热数据节点

代码语言:javascript复制
# cat elasticsearch.yml    // 配置文件设置tag区分
node.attr.tag: cold/hot

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

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

代码语言:javascript复制
#构建索引模板,滚动新增的索引将按照模板进行创建
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 节点

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

其它配置说明

  • 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 秒。在较差的网络环境下需要设置得大一点,防止因误判该节点的存活状态而导致分片的转移。

0 人点赞