Loading

Elasticsearch集群优化实战

版本配置:

ES版本:7.16

OS内存64G。

一、安装部署

1.ES jvm内存31G,预留一半的物理内存给文件系统缓存(file system cache)。

2.禁止内存交换:

  • 修改/etc/sysctl.conf 中 vm.swappiness = 1
  • elasticsearch.yml中,设置这个:bootstrap.mlockall:true

3.修改ES启动用户可使用的系统文件句柄数等。

4.有条件使用更好的硬盘如ssd。

5.如果有多块盘:

  •   做RAID0或者RAID5,RAID可以提高磁盘IO,建议做RAID5。
  •   每个盘mount到一个目录,data path配置多个,多个path会有数据不均衡的问题。

6.节点分开部署:master、data、coordinate

7.冷热分离架构:热数据SSD存储,冷数据普通硬盘存储。

二、合理的Index Mapping

1.特殊字段:如Boolean、IP、时间等。

2.字符串:

尽量使用keyword,默认的text会被analyze。

keyword最大32766字节。

使用keyword存储大字符串,可以作为查询结果,只存储不索引:

"payload" : {
    "type": "keyword",
    "index": false,
    "doc_values": false,
    "ignore_above": 1
}

3.调整refresh间隔:refresh_interval: 30s,默认的1秒会导致大量segment产生,影响性能。

PUT /my_index/_settings
{
  "index": {
    "refresh_interval": "30s"
  }
}

4.调整translog刷新机制为异步:

"index": {
    "translog": {
        "flush_threshold_size": "512mb",  (默认512M,不建议修改)
        "sync_interval": "10s",  (默认5s,可适当增大)
        "durability": "async"   (默认request,每次更新都会写trans log,修改为异步)
    }
}

5.创建新索引时,可以配置每个分片中的Segment的排序方式,index sorting是优化检索性能的非常重要的方式之一:

{
    "settings" : {
        "index" : {
            "sort.field" : "timestamp",
            "sort.order" : "desc"
        }
    },
    "mappings": {
        "properties": {
            "timestamp": {
                "type": "date"
            }
        }
    }
}

6.Text字段类型关闭index和fielddata属性

 "message" : {
    "type" : "text",
    "index" : false,
    "fielddata" : false
}

7.时间字段设置

"event_time": {
    "type": "date",
    "format": "epoch_millis"
}

常用的format格式:

  • epoch_millis: Unix 时间戳,表示自1970年1月1日以来的毫秒数。
  • epoch_second: Unix 时间戳,表示自1970年1月1日以来的秒数。
  • strict_date_optional_time: 允许日期和时间格式,例如 yyyy-MM-dd'T'HH:mm:ss.SSSZ

三、ES参数调整

针对data节点,设置elasticsearch.yml中:

  • thread_pool.bulk.queue_size: 1024 (增大)
  • indices.fielddata.cache.size: 1gb (调小,默认无限制
  • indices.queries.cache.size: 1gb(默认10%,可适当调小)
  • indices.memory.index_buffer_size: 15% (默认10%,会影响写入性能,写入的分片数更多,则需要更多的buffer)
  • cluster.routing.allocation.disk.include_relocations: false (加快shard分配,在建索引的时候,不考虑迁移的任务)

熔断circuit-breaker调整(调低,减小OOM风险):

  • indices.breaker.total.limit: 50% (默认70%的JVM内存)
  • indices.breaker.request.limit: 10% (默认60%的JVM内存)
  • indices.breaker.fielddata.limit: 10% (默认40%的JVM内存)
  • cluster.routing.allocation.same_shard.host:true

如果机器具有128 GB的RAM,可以运行两个节点,每个节点配置31GB内存,Lucene将使用剩余64GB内存。如果这样搭建data节点,在配置中设置cluster.routing.allocation.same_shard.host为true。这将阻止主副本分片被分配到同一台物理机,提高可用性。

watermark机制用于管理集群中节点磁盘空间的使用:

1.Low Watermark (低水位线)

  • 配置项:cluster.routing.allocation.disk.watermark.low: 85%
  • 作用:当节点磁盘使用率超过低水位线时,Elasticsearch 会停止将新的分片分配到这个节点上,但已经在这个节点上的分片不会受到影响。这是为了避免将更多数据写入已经趋近于满的节点上。
2.High Watermark (高水位线)
  • 配置项:cluster.routing.allocation.disk.watermark.high: 90%
  • 作用:当节点磁盘使用率超过高水位线时,Elasticsearch 将尝试将该节点上的分片迁移到其他节点上(如果有足够的空间)。同时,新的分片不会分配到这个节点。

3.Flood Stage Watermark (洪水阶段水位线)

  • 配置项:cluster.routing.allocation.disk.watermark.flood_stage: 95%
  • 作用:当节点磁盘使用率超过洪水阶段水位线时,Elasticsearch 会将这个节点上所有的索引标记为只读。这意味着该节点将停止接收新的写操作(包括文档索引和分片更新),以避免磁盘完全写满而导致更严重的问题。

四、设置合理的分片数和副本数

1.对于数据量较小(100GB以下)的index:一般设置3~5个shard

2.对于数据量较大(100GB以上)的index:一般把单个shard的数据量控制在20GB~40GB

3.对于30G内存的节点,shard数量最好控制在600个(即每1GB内存的shard数在20以内)

4.副本数:一般副本数为1,对数据可用性有高要求的,可以设置为2

五、索引管理、段合并(Segment Merge)

1.基于数据大小和保存时长,按天、周、月、年去创建、关闭、删除索引。

2.索引太多时,索引预创建:每天定时任务把明天需要的索引先创建好(从6.7版本开始kibana自带索引生命周期管理ILM)。

3.关闭索引(文件仍然存在于磁盘,只是释放掉内存),需要的时候可以重新打开。

4.通过_forcemerge API进行合并,减少segments数量,同时提高查询效率:max_num_segments取值为:max_num_segments =(单个索引的大小G/分片数/2G)

5.通过_reindex API将历史小索引合并成大索引,减少索引数和分片数。

6.数据roll up(预聚合,物化视图)

六、写入

1.使用批量请求bulk request。

2.尽量使用自动生成的ID。Elasticsearch自动生成的ID可以确保是唯一的,以避免版本查询。

3.避免索引大的document数据,如超过100M的一条document。

4.减少副本数,字段不分词,可增加写入性能。

七、查询

1.尽量使用filter而不是query。使用filter不会计算评分score,只计算匹配。

2.如果不关心文档返回的顺序,则按_doc排序。

3.避免通配符查询。

4.不要获取太大的结果数据集,如果需要大量数据使用scroll API。

  • 分页查询使用:from+size
  • 遍历使用:scroll
  • 并行遍历使用:scroll+slice

5.关于数据聚合去重

  • terms 指定字段聚合 + topN:合理设置聚合的topN,聚合结果是不精确的,是取每个分片的Top size元素后综合排序后的值。
  • ES5以后的新特性collapse:按某个字段进行“折叠”,这个collapse只针对query出来的结果,只能用在keyword或者numeric类型。
  • ES6以后支持分页的聚合:Composite Aggregation,可以获取全量的聚合数据,只能用于Terms、Histogram、Date histogram、GeoTile grid。

八、中文分词

ik_smart 与 ik_max_word 的异同

  • ik_smart 比较适合 match_phrase query,而 ik_max_word 更合适 term query。
  • ik_smart 的分词结果并不是 ik_max_word 的分词结果的子集。

使用建议

1)召回要求高,对分词词元匹配精准的,使用 ik_max_word,并结合 term 查询。

2)召回要求低,分词切分要求较低,节省存储,比如日志场景,可以考虑 ik_smart 进行 match_phrase查询。

3)索引分词器和搜索分词器原则上保持一致,如果索引使用 ik_max_word 而搜索使用 ik_smart,则有词元匹配失败的可能。

 

参考:

Elasticsearch 8.X 检索实战调优锦囊

为什么Elasticsearch查询变得这么慢了?

图解 Elasticsearch 的 Fielddata Cache 使用与优化

深入解析 Elasticsearch IK 分词器:ik_smart 和 ik_max_word 的区别与应用场景

https://www.elastic.co/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster 

https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-search-speed.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-disk-usage.html 

https://www.elastic.co/guide/en/elasticsearch/reference/7.16/modules-fielddata.html

https://www.elastic.co/guide/en/elasticsearch/reference/7.16/circuit-breaker.html

 

posted @ 2019-04-20 20:24  阿凡卢  阅读(3764)  评论(0编辑  收藏  举报