0%

elasticsearch 集群优化

一、慢日志

分片级别,针对于data node。

现象

  • 连接大量被拒绝
  • CPU居高不下
  • 查询超时

原因

  • 软件配置不合理
  • 硬件资源不够

慢查询和写入配置

慢查询配置

1
2
3
4
5
6
7
8
9
10
11
12
PUT /index/_settings
{
"index.search.slowlog.threshold.query.warn":"10s",
"index.search.slowlog.threshold.query.info":"5s",
"index.search.slowlog.threshold.query.debug":"2s",
"index.search.slowlog.threshold.query.trace":"500ms",
"index.search.slowlog.threshold.fetch.warn":"1s",
"index.search.slowlog.threshold.fetch.info":"800ms",
"index.search.slowlog.threshold.fetch.debug":"500ms",
"index.search.slowlog.threshold.fetch.trace":"200ms",
"index.search.slowlog.level":"info"
}

慢写入配置

1
2
3
4
5
6
"index.indexing.slowlog.threshold.index.warn":"10s",
"index.indexing.slowlog.threshold.index.info":"5s",
"index.indexing.slowlog.threshold.index.debug":"2s",
"index.indexing.slowlog.threshold.index.trace":"500ms",
"index.indexing.slowlog.level":"info"
"index.indexing.slowlog.source":1000

二、优化

搜索优化

  • 减小page size:搜索结果不要返回过大的结果集,每页搜索数据控制在1000以内。
  • 避免deeping:如果需要深度分页,建议使用scroll search,如果一定要使用深查询,考虑使用search after
  • 聚合查询避免过多分桶:对于桶数过多的聚合,应将数据切片:比如按时间、按地理位置等分词请求。
  • 能用filter的地方不要使用query,filter不参与评分效率较query高
  • 避免过多使用agg嵌套
  • 尽量避免使用fuzzy、前缀和正则,可用使用suggest做迷糊搜索

写入优化

  • 用bulk批量写入
  • 使用多线程将数据写入es
  • 大量数据一次性写入es:如果需要一次性写入大量数据,可以先禁止refresh和replica复制,将index.refresd_interval设置为-1,将index.number_of_replicas设置为0。此时es不需要创建segment file文件,也不需要项副本同步数据,相对来水写入速度会非常快,等数据写入完成之后,再将这两个参数设置回来。
  • 增加buffer缓冲区大小:indices.memory.index_buffer_size,一般来说indices.memory.index_buffer_size / total_shards < jvm heap的10%,增大buffer的大小可以大大提高写入速度
  • 把更多内存留给OS Cache:可能有人认为应该把jvm heap调大来增加性能,这都是想当然的操作,我们不仅不应该增大jvm heap,反而应该把更多的内存留给OS Cache,因为lucene底层读写都是基于OS Cache的,需要大量的内存。

数据结构优化

  • 尽量使用手工mapping,尽量手动指定string字段类型
  • 避免稀疏数据结构:会产生磁盘浪费,同时降低读写性能
  • 避免将没有任何关联性的数据写入同一个索引
  • 检索和聚合解耦:避免把大量用于检索的数据和用于聚合的数据放在同一个index
  • 仅用于检索的字段关闭doc value,仅用于聚合的字段关闭index
  • 避免使用fielddata
  • 禁用norms:对于不需要参与评分的字段,可以设置为false,常见的比如filter和agg的字段
  • 禁用index_options
  • 禁用_all field
  • source和store分离(es会将所有字段放入source字段中,每次查询会将整个source返回交给客户端解析;store方式则将每个字段单独存储)
  • 使用最小的数据类型:能用short的不要用long,这一点在es中尤为重要
  • scripting查询参数化:script脚本会触发编译行为,并且产生缓存,使用不当会造成查询巨慢,甚至OOM
  • id:对于某些id字段,不需要我们做全文检索,可以使用keyword,会比数据类型获得更好的性能
  • 业务框架解耦:避免业务对es过多的功能依赖,es本身是一个搜索、存储、分析引擎,尽量把功能依赖放在这三个点上,有些功能虽然es提供了,但是能用其他方案取代就尽量不用es,让es有更多的资源专注于搜索和聚合。即便es提供的解决方案更好,但是代价却是占用了主要的资源,比如智能推荐、模糊查询等

集群优化

  • 冷热分离:高频数据使用性能更好的硬件,HDD < SSD < RAM
  • 单一职责:关闭master节点的data node设置,集群越大,数据节点和master节点越要分开
  • 增加协调节点的数据:稳定的master节点对于集群健康非常重要。理论上讲,应该尽可能减轻master节点的压力,分片数据越多,master节点维护管理shard的任务越重,并且节点可能就要承担更多的数据转发任务,但增加仅协调节点(node.master = false和node.data=false)会增加整个集群的负担,因为选择master需要等待集群每个节点的集群状态确认
  • 高可用集群至少需要三个主节点,其中至少两个不是仅投票节点(Node.voting_only = true)。即使其中一个节点发生故障,集群也能够选举一个主节点。生产环境最好设置三台仅master候选节点(node.master=true node.data=false)
  • 为了确保集群仍然可用,集群不能同时停止投票配置中的一半或更多节点。只要有一半以上的投票节点可用,集群仍可以正常工作。这意味着,如果有两个或更少的主机资格节点,则他们必须保持高可用
  • 禁用swapping:swapping会大大降低性能

索引优化

  • 控制分片数量:每台节点的shard数据越少,每个shard分配的cpu、内存和io资源更多,单个shard的性能越好。当一台机器一个shard时,该shard的性能最好。分片越少,分页查询速度越快。但如果相同资源分片相同的前提下,shard数量越少,单个shard的体积越大,查询性能越低,速度越慢,这个取舍应该根据实际集群状况和结合应用场景等因素总和考虑。单个分片不要太大尽量不要超过20-40G
  • 搜索日志:统计高频词汇,对于命中率极高的关键词添加应用层缓存
  • 冷热分离:把冷热数据放在不同的索引

硬件优化

  • 全能型:数据节点处理与数据相关的操作,例如CRUD、搜索和聚合。这些操作时IO、内存和CPU密集型的,所以他们需要更高配置的服务器以及更高的带宽,并且集群的性能冗余非常重要

  • 带宽:由于仅投票节点不参与master竞选,所以和真正的master节点相比,它需要的内存和CPU较少。但是所有候选节点以及仅投票节点都可能是数据及诶单,所以他们都需要快速稳定低延迟的网络