Elasticsearch运维指南

2021-06-21 10:44:05 浏览数 (1)

1.常用监控工具

1.1 cerebro⼯具

地址:https://github.com/lmenezes/cerebro

1.2 Kibana Stack Monitoring

地址: https://www.elastic.co/guide/en/kibana/current/xpack-monitoring.html

2. 关键指标监控

2.1 集群健康维度:分⽚和节点

通过GET _cluster/health监视群集时,可以查询集群的状态、节点数和活动分⽚计数的信息。还可

以查看重新定位分⽚,初始化分⽚和未分配分⽚的计数。

代码语言:javascript复制
{
  "cluster_name" : "my_cluster",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 43,
  "active_shards" : 77,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 2,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 97.46835443037975
}

集群运⾏的重要指标:

Status:状态群集的状态。红⾊:部分主分⽚未分配。⻩⾊:部分副本分⽚未分配。绿⾊:所有

分⽚分配ok。

Nodes:群集中的节点总数。

Shards:活动分⽚计数。集群中活动分⽚的数量。 Relocating Shards:重定位分⽚。由于节

点丢失⽽移动的分⽚计数。

Initializing Shards:初始化分⽚。由于添加索引等⽽初始化的分⽚计数。

Unassigned Shards:未分配的分⽚。尚未创建或分配副本的分⽚计数。

未分配状态及原因解读:

代码语言:javascript复制
(1)INDEX_CREATED
 Unassigned as a result of an API creation of an index.
(2)CLUSTER_RECOVERED
 Unassigned as a result of a full cluster recovery.
(3)INDEX_REOPENED
 Unassigned as a result of opening a closed index.
(4)DANGLING_INDEX_IMPORTED
 Unassigned as a result of importing a dangling index.
(5)NEW_INDEX_RESTORED
 Unassigned as a result of restoring into a new index.
(6)EXISTING_INDEX_RESTORED
 Unassigned as a result of restoring into a closed index.
(7)REPLICA_ADDED
 Unassigned as a result of explicit addition of a replica.
(8)ALLOCATION_FAILED
 Unassigned as a result of a failed allocation of the shard.
(9)NODE_LEFT
 Unassigned as a result of the node hosting it leaving the cluste
r.
(10)REROUTE_CANCELLED
 Unassigned as a result of explicit cancel reroute command.
(11)REINITIALIZED
When a shard moves from started back to initializing, for exampl
e, with shadow replicas.
(12)REALLOCATED_REPLICA
A better replica location is identified and causes the existing r
eplica allocation to be cancelled.

2.2 搜索性能维度:请求率和延迟

通过测量系统处理请求的速率和每个请求的使⽤时间可以衡量集群的有效性;

当集群收到请求时,可能需要跨多个节点访问多个分⽚中的数据。系统处理和返回请求的速率、当

前正在进⾏的请求数以及请求的持续时间等核⼼指标是衡量集群健康重要因素。

请求过程本身分为两个阶段:

第⼀是查询阶段(query phase),集群将请求分发到索引中的每个分⽚(主分⽚或副本分

⽚)。

第⼆个是获取阶段(fetch phrase),查询结果被收集,处理并返回给⽤户。

通过GET blogs_analyzed/_stats可以查看对应目标索引的状态,search状态查询的结果如下:

代码语言:javascript复制
 "search" : {
        "open_contexts" : 0,
        "query_total" : 0,
        "query_time_in_millis" : 0,
        "query_current" : 0,
        "fetch_total" : 0,
        "fetch_time_in_millis" : 0,
        "fetch_current" : 0,
        "scroll_total" : 0,
        "scroll_time_in_millis" : 0,
        "scroll_current" : 0,
        "suggest_total" : 0,
        "suggest_time_in_millis" : 0,
        "suggest_current" : 0
      }

请求检索性能相关的重要指标如下:

  • query_current:当前正在进⾏的查询数。集群当前正在处理的查询计数。
  • fetch_current:当前正在进⾏的fetch次数。集群中正在进⾏的fetch计数。
  • query_total:查询总数。集群处理的所有查询的聚合数。
  • query_time_in_millis:查询总耗时。所有查询消耗的总时间(以毫秒为单位)。
  • fetch_total:提取总数。集群处理的所有fetch的聚合数。
  • fetch_time_in_millis:fetch所花费的总时间。所有fetch消耗的总时间(以毫秒为单位)。

2.3 索引性能维度:刷新(refresh)和合并(Merge)时间

监视⽂档的索引速率( indexing rate )和合并时间(merge time)有助于在开始影响集群性能之

前提前识别异常和相关问题。将这些指标与每个节点的运⾏状况并⾏考虑,这些指标为系统内的潜

问题提供重要线索,为性能优化提供重要参考。

可以通过GET /_nodes/stats获取索引性能指标,并可以在节点,索引或分⽚级别进⾏汇总。

代码语言:javascript复制
        "merges" : {
          "current" : 0,
          "current_docs" : 0,
          "current_size_in_bytes" : 0,
          "total" : 184,
          "total_time_in_millis" : 23110,
          "total_docs" : 1017919,
          "total_size_in_bytes" : 342535815,
          "total_stopped_time_in_millis" : 0,
          "total_throttled_time_in_millis" : 0,
          "total_auto_throttle_in_bytes" : 524288000
        },
        "refresh" : {
          "total" : 1842,
          "total_time_in_millis" : 20327,
          "external_total" : 1583,
          "external_total_time_in_millis" : 19195,
          "listeners" : 0
        },
        "flush" : {
          "total" : 21,
          "periodic" : 0,
          "total_time_in_millis" : 131
        },

索引性能维度相关重要指标:

  • refresh.total:总刷新计数。刷新总数的计数。
  • refresh.total_time_in_millis:刷新总时间。汇总所有花在刷新的时间(以毫秒为单位进⾏测
  • 量)。
  • merges.current_docs:⽬前的合并。合并⽬前正在处理中。
  • merges.total_docs:合并总数。合并总数的计数。
  • merges.total_time_in_millis。合并花费的总时间。合并段的所有时间的聚合。

2.4 节点运⾏状况维度:内存,磁盘和CPU指标

Elasticsearch是⼀个严重依赖内存 以实现性能的系统,因此密切关注内存使⽤情况与每个节点的

运⾏状况和性能相关。改进指标的相关配置更改也可能会对内存分配和使⽤产⽣负⾯影响,因此记

住从整体上查看系统运⾏状况⾮常重要。

监视节点的CPU使⽤情况并查找峰值有助于识别节点中的低效进程或潜在问题。CPU性能与Java虚

拟机(JVM)的垃圾收集过程密切相关。

代码语言:javascript复制
GET /_cat/nodes?v&h=id,disk.total,disk.used,disk.avail,disk.used_percent,ram.current,ram.percent,ram.max,cpu
id   disk.total disk.used disk.avail disk.used_percent ram.current ram.percent ram.max cpu
jg1X     19.9gb    16.2gb      3.7gb             81.15       1.8gb          96   1.9gb   0
ZnpM     19.9gb    16.4gb      3.4gb             82.52       1.7gb          91   1.9gb   0
Hyt2     19.9gb    16.2gb      3.7gb             81.16       1.8gb          96   1.9gb   0

节点运⾏的重要指标:

  • disk.total :总磁盘容量。节点主机上的总磁盘容量。
  • disk.used:总磁盘使⽤量。节点主机上的磁盘使⽤总量。
  • avail disk:可⽤磁盘空间总量。
  • disk.avail disk.used_percent:使⽤的磁盘百分⽐。已使⽤的磁盘百分⽐。
  • ram:当前的RAM使⽤情况。当前内存使⽤量(测量单位)。
  • percent ram:RAM百分⽐。正在使⽤的内存百分⽐。
  • max : 最⼤RAM。 节点主机上的内存总量
  • cpu:中央处理器。正在使⽤的CPU百分⽐。

2.4.1 如何查看io压⼒

代码语言:javascript复制
1 iostat -d -k 1 10     #查看TPS和吞吐量信息(磁盘读写速度单位为KB)
2 iostat -d -m 2        #查看TPS和吞吐量信息(磁盘读写速度单位为MB)
3 iostat -d -x -k 1 10  #查看设备使⽤率(%util)、响应时间(await)
4 iostat -c 1 10        #查看cpu状态实例分析

可以根据 iowait , ioutil 等值来综合判断. 当iowait⻓期接近100%基本代表io系统出现瓶颈了。这时候可

以⽤iotop命令来诊断出具体是什么进程在消耗io资源。

2.5 JVM运⾏状况维度:堆,GC和池⼤⼩(Pool Size)

作为基于Java的应⽤程序,Elasticsearch在Java虚拟机(JVM)中运⾏。JVM在其“堆”分配中管

理其内存,并通过garbage collection进⾏垃圾回收处理。

如果应⽤程序的需求超过堆的容量,则应⽤程序开始强制使⽤连接的存储介质上的交换空间。虽然

这可以防⽌系统崩溃,但它可能会对集群的性能造成严重破坏。监视可⽤堆空间以确保系统具有⾜

够的容量对于集群的健康⾄关重要。

JVM内存分配给不同的内存池。您需要密切注意这些池中的每个池,以确保它们得到充分利⽤并且

没有被超限利⽤的⻛险。

垃圾收集器(GC)很像物理垃圾收集服务。我们希望让它定期运⾏,并确保系统不会让它过载。理

想情况下,GC性能视图应类似均衡波浪线⼤⼩的常规执⾏。尖峰和异常可以成为更深层次问题的指

标。

可以通过GET /_nodes/stats 命令检索JVM度量标准。

代码语言:javascript复制
      "jvm" : {
        "timestamp" : 1623964232904,
        "uptime_in_millis" : 5786635,
        "mem" : {
          "heap_used_in_bytes" : 294418688,
          "heap_used_percent" : 28,
          "heap_committed_in_bytes" : 1038876672,
          "heap_max_in_bytes" : 1038876672,
          "non_heap_used_in_bytes" : 167878480,
          "non_heap_committed_in_bytes" : 181440512,
          "pools" : {
            "young" : {
              "used_in_bytes" : 153960136,
              "max_in_bytes" : 279183360,
              "peak_used_in_bytes" : 279183360,
              "peak_max_in_bytes" : 279183360
            },
            "survivor" : {
              "used_in_bytes" : 12341536,
              "max_in_bytes" : 34865152,
              "peak_used_in_bytes" : 34865136,
              "peak_max_in_bytes" : 34865152
            },
            "old" : {
              "used_in_bytes" : 128117016,
              "max_in_bytes" : 724828160,
              "peak_used_in_bytes" : 128117016,
              "peak_max_in_bytes" : 724828160
            }
          }
        },
        "threads" : {
          "count" : 108,
          "peak_count" : 114
        },
        "gc" : {
          "collectors" : {
            "young" : {
              "collection_count" : 256,
              "collection_time_in_millis" : 2136
            },
            "old" : {
              "collection_count" : 2,
              "collection_time_in_millis" : 151
            }
          }
        },

JVM运⾏的重要指标如下:

  • mem:内存使⽤情况。堆和⾮堆进程和池的使⽤情况统计信息。
  • threads:当前使⽤的线程和最⼤数量。
  • gc:垃圾收集。算和垃圾收集所花费的总时间。

3. 常⽤命令清单

3.1 查看集群状态

代码语言:javascript复制
# 集群状态查看
GET _cluster/health
# 找到对应的索引,health可选值green, yellow, red
GET /_cat/indices?v&health=red
# 详细查看未分配原因
GET _cluster/allocation/explain
# 查看具体的索引,分⽚以及未分配原因
GET _cat/shards?h=index,shard,prirep,state,unassigned.reason&v
# 查看数据分布情况
GET _cat/allocation?v

3.2 节点间分⽚移动

⼿动移动分配分⽚。将启动的分⽚从⼀个节点移动到另⼀节点。

代码语言:javascript复制
POST /_cluster/reroute
{
  "commands": [
    {
      "move": {
        "index": "indexname",
        "shard": 1,
        "from_node": "nodename",
        "to_node": "nodename"
      }
    }
  ]
}

POST /_cluster/reroute
{
  "commands": [
    {
      "move": {
        "index": "test",
        "shard": 0,
        "from_node": "node1",
        "to_node": "node2"  # 将test 的shard 0分⽚从node1移动到nod
e2
      }
    },
    {
      "allocate_replica": {
        "index": "test",
        "shard": 1,
        "node": "node3"   # test索引的shard 1 分配到node3
      }
    },
    {
      "cancel": {
        "index": "test",
        "shard": 0,
        "node": "node2"   # 取消在node2上⾯分配test的shard 0 分⽚
      }
    }
  ]
}

allocate_stale_primary:以集群内存在的陈旧的分⽚内容,再次分配。
allocate_empty_primary:分配空内容的分⽚

POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_stale_primary": {
        "index": "dcvs_aps",
        "shard": 3,
        "node": "MYSQL2",
        "accept_data_loss": true
      }
    }
  ]
}

设置分配的最⼤失败重试次数,默认是5次,当然系统分配到达重试次数后,可以⼿动分配分⽚ 。"index.allocation.max_retries" : "5",

代码语言:javascript复制
POST _cluster/reroute?retry_failed

3.3 集群节点优雅下线

保证集群颜⾊绿⾊的前提下,将某个节点优雅下线。

代码语言:javascript复制
PUT /_cluster/settings
{
  "transient": {
    "cluster.routing.allocation.exclude._ip": "192.168.248.1"
  }
}

3.4 强制刷新

刷新索引是确保当前仅存储在事务⽇志中的所有数据也永久存储在Lucene索引中。

注意:7.6及之后版本会废弃同步刷新改⽤_flush

代码语言:javascript复制
 # >=7.6版本
 POST /_flush

 # <7.6版本使⽤同步刷新
 POST /_flush/synced

3.5 更改并发分⽚的数量以平衡集群

控制在集群范围内允许多少并发分⽚重新平衡。默认值为2。

代码语言:javascript复制
PUT /_cluster/settings
{
  "transient": {
    "cluster.routing.allocation.cluster_concurrent_rebalance": 2
  }
}

3.6 开启和关闭分片自动重均衡

Elasticsearch在业务高峰期进行分片重均衡会造成网络延迟或者io异常等现象,所以可以选择在业务低峰期开启ES分片自动均衡。

代码语言:javascript复制
关闭ES自动重均衡
PUT _cluster/settings
{
  "transient": {
    "cluster.routing.rebalance.enable":"none"
  }
}
开启ES自动重均衡
PUT _cluster/settings
{
  "transient": {
    "cluster.routing.rebalance.enable":"all"
  }
}

注释:

  • transient:临时调整集群配置,整个集群重启后,对应参数失效;
  • persistent: 永久调整集群配置,整个集群重启后,对应参数仍然有效;

3.7 更改每个节点同时恢复的分⽚数量

如果节点已从集群断开连接,则其所有分⽚将都变为未分配状态。经过⼀定的延迟后,分⽚将分配到其他

位置。每个节点要恢复的并发分⽚数由该设置确定。

代码语言:javascript复制
PUT /_cluster/settings
{
  "transient": {
    "cluster.routing.allocation.node_concurrent_recoveries": 6
  }
}

3.8 调整恢复速度

为了避免集群过载,Elasticsearch限制了分配给恢复的速度。你可以仔细更改该设置,以使其恢复更快。

如果此值调的太⾼,则正在进⾏的恢复可能会消耗过多的带宽和其他资源,这可能会使集群不稳定。

代码语言:javascript复制
PUT /_cluster/settings
{
  "transient": {
    "indices.recovery.max_bytes_per_sec": "80mb"
  }
}

3.9 清除节点上的缓存

如果节点达到较⾼的JVM值,则可以在节点级别上调⽤该API 以使 Elasticsearch 清理缓存。

注意:这会降低性能,但可以使你摆脱OOM(内存不⾜)的困扰。

代码语言:javascript复制
 # 清除所有索引的所有缓存
 POST /_cache/clear

 # 清除特定索引的特定cache
 POST /my-index-000001/_cache/clear?fielddata=true
 POST /my-index-000001/_cache/clear?query=true
 POST /my-index-000001/_cache/clear?request=true

3.10 调整断路器

断熔器通过内部检查(字段的类型、基数、⼤⼩等等)来估算⼀个查询需要的内存。它然后检查要求加载的 fielddata 是否会导致 fielddata 的总量超过堆的配置⽐例。

如果估算查询的⼤⼩超出限制,就会触发断路器,查询会被中⽌并返回异常。这都发⽣在数据加载之前,也就意味着不会引起 OutOfMemoryException 。

代码语言:javascript复制
#1.查看断路器
GET /_nodes/stats/breaker?pretty
GET /_cluster/settings?include_defaults&flat_settings

#2.⽗断路器:默认95%,所有断路器的⽗断路器,保证所有的heap使⽤率不会超过该值
indices.breaker.total.limit

#3.fielddata断路器:fielddata断路器可以估算每⼀个field的所有数据被加载到内存中,需要耗费多⼤的内存。
 # 默认40%heap,7.9之前是60%
 indices.breaker.fielddata.limit
 #可以配置估算因⼦,估算出来的值会乘以这个估算因⼦,留⼀些buffer,默认是1.03。
 indices.breaker.fielddata.overhead
indices.breaker.fielddata.limit 必须⼤于 indices.fielddata.cache.size,否则只会触发fielddata
circuit breaker,⽽不会剔除旧的fielddata。

#4.request circuit breaker
request circuit breaker可以阻⽌由于某个请求对应的⼀些数据结构造成的OOM(⽐如⼀个聚合请求可能
会⽤jvm内存来做⼀些汇总计算)。
indices.breaker.request.limit # 默认 60%

#5.in flight request circuit breaker
flight request circuit breaker可以限制当前所有进来的transport或http层的请求所使⽤内存总量,这个
内存的使⽤量就是请求⾃⼰本身的⻓度。
network.breaker.inflight_requests.limit # 默认100%
设置方法如下:
PUT /_cluster/settings
{
  "persistent": {
    "indices.breaker.total.limit": "40%"
  }
}

3.11 ElasticSearch 使⽤低速设备的 Tips

单个分⽚上⼀次合并的最⼤线程数。该参数影响lucene后台的合并线程数量,默认设置只适合SDD。如果多个合并线程可能导致io压⼒过⼤。

代码语言:javascript复制
PUT movies/_settings
{
  "index.merge.scheduler.max_thread_count":1
}

3.12 限制每个节点分⽚数

index级别上设置index.routing.allocation.total_shards_per_node 避免同⼀个index的多个shard分配到同⼀个node

代码语言:javascript复制
# index级别
index.routing.allocation.total_shards_per_node

# node级别,所有索引
cluster.routing.allocation.total_shards_per_node

3.13 查看任务tasks

返回集群中⼀个或多个节点上当前执⾏的任务信息。

代码语言:javascript复制
 GET _tasks
 GET _tasks?nodes=nodeId1,nodeId2
 GET _tasks?nodes=nodeId1,nodeId2&actions=cluster:*


 # task详情
 GET /_tasks/<task_id>
 GET _tasks/oTUltX4IQMOUUVeiohTt8A:124
 GET _tasks?actions=*search&detailed

3.14 取消任务

代码语言:javascript复制
 POST _tasks/oTUltX4IQMOUUVeiohTt8A:12345/_cancel
 POST _tasks/_cancel?nodes=nodeId1,nodeId2&actions=*reindex

3.15 查看pending tasks

返回尚未执⾏的集群级更改列表,如创建索引、更新映射、分配碎⽚等。

代码语言:javascript复制
 GET /_cluster/pending_tasks
 GET /_cat/pending_tasks

3.16 集群级别分⽚分配

代码语言:javascript复制
# 启⽤或禁⽤对特定种类的分⽚的分配
cluster.routing.allocation.enable: all # 默认all
all -(默认值)允许为所有类型的分⽚分配分⽚。
primaries -仅允许为主分⽚分配。
new_primaries -仅允许为新索引的主分⽚分配。
none -不允许对任何索引进⾏任何类型的分⽚分配。
# ⼀个节点上允许进⾏多少并发的传⼊分⽚恢复
 cluster.routing.allocation.node_concurrent_incoming_recoveries #
认2
 # ⼀个节点上允许进⾏多少并发的传出分⽚恢复
 cluster.routing.allocation.node_concurrent_outgoing_recoveries #
认2
 # 同时设置以上两个值
 cluster.routing.allocation.node_concurrent_recoveries
 # 节点初始化主分⽚数
 cluster.routing.allocation.node_initial_primaries_recoveries #
默认4

3.17 分⽚平衡配置

群集的平衡仅取决于每个节点上的分⽚数量以及这些分⽚所属的索引

代码语言:javascript复制
 # 为特定种类的分⽚启⽤或禁⽤重新平衡
 cluster.routing.rebalance.enable
 all -(默认值)允许所有种类的分⽚进⾏分⽚平衡。
 primaries -仅允许对主要分⽚进⾏分⽚平衡。
 replicas -仅允许对副本分⽚进⾏分⽚平衡。
 none -任何索引都不允许任何形式的分⽚平衡。

 # 允许控制在集群范围内允许多少并发分⽚重新平衡。默认为2
 cluster.routing.allocation.cluster_concurrent_rebalance

3.18 基于磁盘的分⽚分配

代码语言:javascript复制
# 默认为true。设置为false禁⽤磁盘分配决定器。
cluster.routing.allocation.disk.threshold_enabled
cluster.routing.allocation.disk.threshold_enabled # 默认true,启⽤磁盘空间阈值检查
cluster.routing.allocation.disk.watermark.low # 默认85%,分⽚不会分配(除新建的索引的主分⽚不受影响)
cluster.routing.allocation.disk.watermark.high # 默认90%,达到该值,ES会做relocate,影响所有分⽚
cluster.routing.allocation.disk.watermark.flood_stage # 默认95%, index.blocks.read_only_allow_delete,当磁盘使⽤率低于95%,(>=7.4)⾃动释放index.blocks
cluster.info.update.interval # 默认30s设置多久检查⼀次磁盘
# 可以配置具体⼤⼩
PUT _cluster/settings
{
  "transient": {
    "cluster.routing.allocation.disk.watermark.low": "100gb",
    "cluster.routing.allocation.disk.watermark.high": "50gb",
    "cluster.routing.allocation.disk.watermark.flood_stage": "10gb",
    "cluster.info.update.interval": "1m"
  }
}

 # 或者使⽤百分⽐
PUT _cluster/settings
{
  "transient": {
    "cluster.routing.allocation.disk.watermark.low": "85%",
    "cluster.routing.allocation.disk.watermark.high": "90%",
    "cluster.routing.allocation.disk.watermark.flood_stage": "95%",
    "cluster.info.update.interval": "1m"
  }
}
 # 当磁盘使⽤率超过flood_stage阈值是索引被设置为只读,可通过以下命令⼿动恢复读写
 PUT /my-index-000001/_settings
 {
 "index.blocks.read_only_allow_delete": null
 }

3.19 Segment查看段/合并段

代码语言:javascript复制
GET /twitter/_segments
POST /twitter/_forcemerge?max_num_segments=1

3.20 关闭模糊_all / *删除(避免误删)

代码语言:javascript复制
 PUT _cluster/settings
{
"persistent": {
"action.destructive_requires_name":true
}
}

4.总结:

全文总结全文总结

本文主要从常用监控工具,指标阶段,运维常用命令等三方面简单的介绍了Elasticsearch运维的方向,由于运维涉及的知识比较丰富,包括如何做到,双活、高可用、备份策略应如何设定等都和运维息息相关。如果全写篇幅过长,后面作者将以新章节的形式一一分享ES的运维和开发的经验。

0 人点赞