目前生产在用的索引模板。索引调优只是es调优的一部分,还包括硬件,jvm ,集群调优,系统级别的调优等。
索引模版

注意:对于已经创建的索引不会生效,只有新建索引并且索引以logstash-kafka 开头的时候才会使用你的模版。order字段为优先级,数字越大优先级越高。

PUT _template/logstash-kafka
{
      "order": 6,
      "template": "logstash-kafka*",
      "settings": {
         "index.merge.policy.segments_per_tier": "25",
         "index.warmer.enabled": "false",
         "index.refresh_interval": "60s",
         "index.number_of_shards": "7",
         "index.translog.durability": "async",
         "index.store.type": "mmapfs",
         "index.merge.policy.floor_segment": "50mb",
         "index.merge.scheduler.max_thread_count": "1",
         "index.translog.sync_interval": "60s",
         "index.routing.allocation.total_shards_per_node": "2",
         "index.number_of_replicas": "1"
      },
      "mappings": {
      "_default_": {
        "dynamic_templates": [
          {
            "message_field": {
              "path_match": "message",
              "mapping": {
                "norms": false,
                "type": "text"
              },
              "match_mapping_type": "string"
            }
          },
          {
            "string_fields": {
              "mapping": {
                "norms": false,
                "type": "text",
                "fields": {
                  "keyword": {
                    "ignore_above": 256,
                    "type": "keyword"
                  }
                }
              },
              "match_mapping_type": "string",
              "match": "*"
            }
          }
        ],
        "_all": {
          "norms": false,
          "enabled": true
        },
        "properties": {
          "@timestamp": {
            "include_in_all": false,
            "type": "date"
          },
          "geoip": {
            "dynamic": true,
            "properties": {
              "ip": {
                "type": "ip"
              },
              "latitude": {
                "type": "half_float"
              },
              "location": {
                "type": "geo_point"
              },
              "longitude": {
                "type": "half_float"
              }
            }
          },
          "@version": {
            "include_in_all": false,
            "type": "keyword"
          }
        }
      }
    },
    "aliases": {}
  }
}
replica数目

为了让创建的es index在每台datanode上均匀分布,同一个datanode上同一个index的shard数目不应超过3个。
计算公式: (number_of_shard * (1+number_of_replicas)) < 3*number_of_datanodes

每台机器上分配的shard数目

"index.routing.allocation.total_shards_per_node": "2",
refresh时间间隔

默认的刷新时间间隔是1s,对于写入量很大的场景,这样的配置会导致写入吞吐量很低,适当提高刷新间隔,可以提升写入量,代价就是让新写入的数据在60s之后可以被搜索,新数据可见的及时性有所下降。

"index.refresh_interval": "60s"
translog

降低数据flush到磁盘的频率。如果对数据丢失有一定的容忍,可以打开async模式。

"index.translog.flush_threshold_ops": "1000000",
"index.translog.durability": "async",
merge相关参数
"index.merge.policy.floor_segment": "100mb",
"index.merge.scheduler.max_thread_count": "1",
"index.merge.policy.min_merge_size": "10mb"
mapping设置

对于不参与搜索的字段(fields), 将其index方法设置为no, 如果对分词没有需求,对参与搜索的字段,其index方法设置为not_analyzed。
index分为3种模式(简单的说):
1.not_analyzed 进行整个字段的搜索,打个比方对整个单词可以搜索,单词的一部分是搜索不到的。
2.analyzed 对正文可以关键词搜索,只要有你查询的关键字就可以搜索到
3.no 不能进行搜索,也就是关闭搜索功能

不过作为elk查看日志最好要打开分词并且可以进行搜索

"index": "analyzed",
硬件

当然是ssd啦,反正是加上各种资源。

系统级别
文件句柄

Linux中,每个进程默认打开的最大文件句柄数是1000,对于服务器进程来说,显然太小,通过修改/etc/security/limits.conf来增大打开最大句柄数
* - nofile 65535

虚拟内存设置

max_map_count定义了进程能拥有的最多内存区域

sysctl -w vm.max_map_count=262144

修改/etc/elasticsearch/elasticsearch.yml

bootstrap.mlockall: true

修改/etc/security/limits.conf, 在limits.conf中添加如下内容

* soft memlock unlimited
* hard memlock unlimited

TCP全连接队列参数设置, 这样设置的目的是防止节点数较多(比如超过100)的ES集群中,节点异常重启时全连接队列在启动瞬间打满,造成节点hang住,整个集群响应迟滞的情况

echo "net.ipv4.tcp_abort_on_overflow = 1" >>/etc/sysctl.conf
echo "net.core.somaxconn = 2048" >>/etc/sysctl.conf

降低tcp alive time,防止无效链接占用链接数

echo 300 >/proc/sys/net/ipv4/tcp_keepalive_time
磁盘缓存相关参数

vm.dirty_background_ratio 这个参数指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如5%)就会触发pdflush/flush/kdmflush等后台回写进程运行,将一定缓存的脏页异步地刷入外存;

vm.dirty_ratio

该参数则指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如10%),系统不得不开始处理缓存脏页(因为此时脏页数量已经比较多,为了避免数据丢失需要将一定脏页刷入外存);在此过程中很多应用进程可能会因为系统转而处理文件IO而阻塞。

把该参数适当调小,原理通(1)类似。如果cached的脏数据所占比例(这里是占MemTotal的比例)超过这个设置,系统会停止所有的应用层的IO写操作,等待刷完数据后恢复IO。所以万一触发了系统的这个操作,对于用户来说影响非常大的。

sysctl -w vm.dirty_ratio=10
sysctl -w vm.dirty_background_ratio=5
swap调优

swap空间是一块磁盘空间,操作系统使用这块空间保存从内存中换出的操作系统不常用page数据,这样可以分配出更多的内存做page cache。这样通常会提升系统的吞吐量和IO性能,但同样会产生很多问题。页面频繁换入换出会产生IO读写、操作系统中断,这些都很影响系统的性能。这个值越大操作系统就会更加积极的使用swap空间。

调节swappniess方法如下

sudo sh -c 'echo "0">/proc/sys/vm/swappiness'
io sched

如果集群中使用的是SSD磁盘,那么可以将默认的io sched由cfq设置为noop

sudo sh -c 'echo "noop">/sys/block/sda/queue/scheduler
JVM参数设置

1.jvm.options
-Xms和-Xmx设置为相同的值,推荐设置为机器内存的一半左右,剩余一半留给系统cache使用。
jvm内存建议不要低于2G,否则有可能因为内存不足导致ES无法正常启动或OOM
jvm建议不要超过32G,否则jvm会禁用内存对象指针压缩技术,造成内存浪费
2.elasticsearch.yml
设置内存熔断参数,防止写入或查询压力过高导致OOM,具体数值可根据使用场景调整。

indices.breaker.total.limit: 30%
indices.breaker.request.limit: 6%
indices.breaker.fielddata.limit: 3%

调小查询使用的cache,避免cache占用过多的jvm内存,具体数值可根据使用场景调整。

indices.queries.cache.count: 500
indices.queries.cache.size: 5%
集群调优
{
  "persistent": {
    "cluster": {
      "routing": {
        "allocation": {
          "allow_rebalance": "indices_primaries_active",
          "cluster_concurrent_rebalance": "8",
          "node_concurrent_recoveries": "8",
          "enable": "new_primaries"
        }
      }
    },
    "indices": {
      "store": {
        "throttle": {
          "max_bytes_per_sec": "50mb"
        }
      }
    }
  },
  "transient": {
    "cluster": {
      "routing": {
        "rebalance": {
          "enable": "all"
        },
        "allocation": {
          "disk": {
            "include_relocations": "true",
            "threshold_enabled": "true",
            "watermark": {
              "low": "85%",
              "high": "90%"
            }
          }
        }
      },
      "info": {
        "update": {
          "interval": "30s"
        }
      }
    },
    "indices": {
      "breaker": {
        "fielddata": {
          "limit": "30%"
        },
        "request": {
          "limit": "30%"
        }
      }
    }
  }
}
Disk-based Shard Allocation
“cluster.routing.allocation.disk.threshold_enabled”:true,//是否开启基于硬盘的分发策略
 “cluster.routing.allocation.disk.watermark.low”:“85%”,//不会分配分片到硬盘使用率高于这个值的节点
 “cluster.routing.allocation.disk.watermark.high”:“90%”,//如果硬盘使用率高于这个值,则会重新分片该节点的分片到别的节点
 “cluster.info.update.interval”:“30s”,//当前硬盘使用率的查询频率
 “cluster.routing.allocation.disk.include_relocations”:true,//计算硬盘使用率时,是否加上正在重新分配给其他节点的分片的大小
 new_primaries,仅仅对新建索引的primary shard允许分配
 cluster.routing.allocation.node_concurrent_recoveries: 2添加删除节点或负载均衡时并发恢复线程的个数,默认为4
 indices_primaries_active,仅仅只有在所有的primary shard都被分配之后才允许rebalance
 indices_all_active,默认,仅仅允许所有的primary shard和replica shard都被分配之后,才能rebalance
关闭不必要的index

open的索引的shard会加载到内存中,close不必要的index可以减少内存占用。

curl -XPOST http://node01:1 9200/myshard/_close
集群启动数据恢复相关参数配置

集群维护后重启。比如一共5个节点,其中3个节点启动很快,2个节点启动很慢。
当3个节点启动后,另外两个节点还没启动,这个时候集群找不到没启动服务的节点上的shard,这个时候集群就会尝试做分片的重新分配。等另外两个节点启动后,集群再次对集群的分片重新分配。这样就导致了不必要的IO操作,对性能影响非常大。
gateway.recover_after_nodes: 3 当集群中至少启动3个节点,才开始做分片的分配。默认为1

副本、分片数量的规划

分片的数量(建议3~4个)需要根据实际数据量测试,确定最合适的分片数量。
分片数过少,并发少。分片数过多,消耗的系统资源多(打开文件句柄、内存),影响性能。
一个分片最多能存储20亿条记录,根据实际性能规划。
副本一般推荐设置2~3个(大量数据情况)。
副本数量能提升数据检索的性能。
副本需要从主分片同步数据,为了避免服务器压力,副本数量不能过多。