(九)elasticsearch常见问题总结

文章目录

  • (九)elasticsearch常见问题总结
  • 1:问题汇总
  • 1.1:分片未分配:unassigned_shards
  • 1:unassigned原因
  • 2:ALLOCATION_FAILED 分片分配失败解决
  • 3:CLUSTER_RECOVERED集群重启恢复而未分配
  • 4:DANGLING_INDEX_IMPORTED悬空索引分配失败
  • 5:INDEX_CREATED创建索引后分配失败
  • 6:NODE_LEFT节点掉线延迟分配
  • 7:禁止了分片分配导致副本分片未分配
  • 1.2:es写入报:Elasticsearch exception [type=es_rejected_execution_exception, reason=rejected
  • 1.3:节点启动报:java.lang.IllegalStateException: failed to obtain node locks
  • 1.4:高内存/高cpu使用率解决
  • 1.5:大分片处理
  • 2:实战记录
  • 2.1:es写入异常,写入缓慢
  • 2.2:es的节点个数规划


1:问题汇总

1.1:分片未分配:unassigned_shards

现象:GET _cluster/health看到unassigned_shards
分析出未分配的分片信息及未分配的原因:用kibana或者curl均可

方式1:kibana
获取故障分片:get _cat/shards?v&h=index,shard,prirep,state,node,unassigned.reason
具体原因查看:GET /_cluster/allocation/explain
{
  "index": "index",
  "shard": 0,               //shardnum。shardnum:可由GET _cat/shards?v 查看获取
  "primary": false
}

方式2:用curl分析原因
curl -XGET "http://ip:port/_cat/shards?v&h=index,shard,prirep,state,node,unassigned.reason" > shards.txt
获取索引名:cat shards.txt | grep UNASSIGNED
获取具体的分片失败原因:curl -XGET "http://IP:PORT/_cluster/allocation/explain?pretty" -H 'Content-Type:application/json' -d '{"index":"indexName","shard":shardnum,"primary":false}'
shardnum:可由GET _cat/shards?v 查看获取,
1:unassigned原因

结果的explanation中有unassigned具体未分配原因,分片unassigned的类型包括:

ALLOCATION_FAILED: 由于分片分配失败而未分配。
CLUSTER_RECOVERED:由于完整的集群恢复而未分配。
DANGLING_INDEX_IMPORTED: 由于悬空索引而未分配。
EXISTING_INDEX_RESTORED: 由于恢复到封闭索引而未分配。
FORCED_EMPTY_PRIMARY:上次修改分片的分配是通过使用集群重新路由API 强制一个空的主分片。
INDEX_CLOSED: 未分配,因为索引已关闭。
INDEX_CREATED: 由于 API 创建索引而取消分配。
INDEX_REOPENED: 由于打开封闭索引而未分配。
MANUAL_ALLOCATION: 分片的分配最后由集群重新路由API修改。
NEW_INDEX_RESTORED: 由于恢复到新索引而未分配。
NODE_LEFT:由于托管它的节点离开集群而未分配。
NODE_RESTARTING:与 类似NODE_LEFT,不同之处在于节点是使用 Node shutdown API注册为重新启动的。
PRIMARY_FAILED: 分片初始化为副本,但主分片在初始化完成前失败。
REALLOCATED_REPLICA:识别出更好的副本位置并导致现有副本分配被取消。
REINITIALIZED:当分片从启动回到初始化时。
REPLICA_ADDED:由于显式添加副本而未分配。
REROUTE_CANCELLED: 由于显式取消重新路由命令而未分配。

解决根本目的是找到未分配的原因解决并分配

2:ALLOCATION_FAILED 分片分配失败解决
执行		POST _cluster/reroute?retry_failed=true
3:CLUSTER_RECOVERED集群重启恢复而未分配

发生情形:集群停止前关闭了分片分配,开启后没有开启分片分配导致的没有分配
解决:

PUT _cluster / settings { 
"persistent" : { "cluster.routing.allocation.enable" : null } }
4:DANGLING_INDEX_IMPORTED悬空索引分配失败

发送情形:在集群有节点离线的时候执行了删除索引的命令,导致分配在离线节点上的分配未能分配导致的。
解决:

  • 1:列出悬空索引:GET /_dangling 从结果中可以发现索引的名称和UUID
  • 2:重新执行delete index重新删除索引或者导入索引。
  • 3:导入或删除索引:POST/DELETE /_dangling/<index-uuid>?accept_data_loss=true
5:INDEX_CREATED创建索引后分配失败

发送情形:一般是对索引创建或者分配分配做了限制导致路由后分配失败了。
解决:根据GET /_cluster/allocation/explain中的原因查看是哪个参数导致的进行参数调整。
再执行 POST _cluster/reroute?retry_failed=true

6:NODE_LEFT节点掉线延迟分配

发生情形:由于节点掉线导致的分配一般为了保持节点掉线的集群稳定性,所以设置的离线后延迟分配。
PUT _all / _settings { “设置” :{ “index.unassigned.node_left.delayed_timeout” :“5m” } }
解决:取消延迟分配的设置

PUT _all/_settings
{
  "settings": {
    "index.unassigned.node_left.delayed_timeout": "0"
  }
}
7:禁止了分片分配导致副本分片未分配

routing.allocation.enable" : “all”
开启

curl -XPUT 'localhost:9200/_cluster/settings'-d
'{ "transient":
  {"cluster.routing.allocation.enable" : "all" }
}'

其他未分配常规原因及解决方案:

1、单节点索引分片总数超限
2、已达到每个节点的分片总数

重新配置其对应的配置,或进行集群均衡,触发分配等

curl -XPUT "http://194.168.223.20:24100/_cluster/settings?pretty&master_timeout=180s" 
-H 'Content-Type:application/json' -d '{"transient":{"cluster.routing.allocation.allow_rebalance":"indices_primaries_active"}}'
再执行手动重新分片:POST _cluster/reroute?retry_failed=true
执行完分片会移动分配:GET _cluster/health 查看unassigned_shards是否减少

1.2:es写入报:Elasticsearch exception [type=es_rejected_execution_exception, reason=rejected

ElasticsearchException[Elasticsearch exception [type=es_rejected_execution_exception, reason=rejected execution of processing of [114475]
[indices:data/write/bulk[s][p]]: request: BulkShardRequest [[index][11]] containing [52] requests, target allocation id:sWzFdprSRRCQzyeBZGqttQ,
primary term: 1 on EsThreadPoolExecutor[name =ip/write, queue capacity = 1000, org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@d44250d
[Running, pool size = 40,active threads = 40, queued tasks = 1075, completed tasks = 44022]]]]

解决分析集群健康状态

原因1:查看集群状态以及集群告警以及历史告警
	get cluster/health    详细解释看运维篇
	查看是否有未分配的分片,正在迁移的分区进行解决,先停止入库待恢复后再开启,实际中迁移数小于30对写入影响不大
	未分配的分片和迁移分片会导致集群分配缓慢导致写入缓慢
	
原因2::查看写入量是否剧增,分片过大(大于50G)导致
	调整分片数量
	
原因3:查看写入索引的分片分布是否均衡
	GET _cat/shards/index         不均衡进行分片均衡,进行分片分配优化,设置索引的setting。
	最主要参数:total_shards_per_node(单个节点上单个索引分配分片最多个数)
	put index/settings{
	 "routing" : {
          "allocation" : {
            "total_shards_per_node" : "4"
          }
        },
	}
	
原因4:	线程情况:GET _cat/thread_pool?v&s=rejected:desc
	查看线程情况和集群中的状态ip是否高度一致,如果是则看是否分片或者id写入产生了数据倾斜,考虑进行均衡
	reroute迁移配置后开启"routing": {"allocation.enable": "all"}
原因5:查看是否节点cpu/jvm内部压力过高

1.3:节点启动报:java.lang.IllegalStateException: failed to obtain node locks

Caused by: java.lang.IllegalStateException: failed to obtain node locks, tried [] with lock id 
[0]; maybe these locations are not writable or multiple nodes were started without increasing 
[node.max_local_storage_nodes] (was [1])?

集群节点还没有关闭就执行了启动过程,导致的节点注册异常
jps找到进程,kill -9 pid杀死重启

1.4:高内存/高cpu使用率解决

1:现象
节点的内存和cpu使用率过高,一般85%作为分界线;客户端的读写等请求会被拒绝

1cpu:GET _cat/nodes?v=true&s=cpu:desc
2内存:GET _nodes/stats?filter_path=nodes.*.jvm.mem.pools.old

使用率过高再查看热点线程是那些GET _nodes/my-node,my-other-node/hot_threads
2:解决方案

  • 减少内存压力
    1:对于text字段,fielddata 可以使用大量的 JVM 内存。为避免这种情况,Elasticsearchtext默认禁用字段上的 fielddata
    2:清除fielddata缓存 POST _cache/clear?fielddata=true
    3:减少分片数量,减少副本的梳理比如3->2
    4:避免大数据量的查询,减少返回的数据量。size使用 索引设置
    降低限制index.max_result_window。
    使用search.max_buckets集群设置 减少允许的聚合桶的最大数量 。
    使用 search.allow_expensive_queries集群设置禁用昂贵的查询。
  • 减少cpu压力
    对bulk批请求进行测试,避免一批请求过多
    GET _nodes/my-node,my-other-node/hot_threads获取热点线程,取消长时间运行的请求
    进行扩容,查看是否有超大分片索引进行解决

1.5:大分片处理

1、大分片的危害

  • 过度占用服务器资源,降低集群服务能力
  • 加剧JVM的GC,导致查询,写入变慢
  • 在进行索引恢复,数据均衡时,更耗时
  • 集群故障恢复变慢
  • 集群稳定性变差

2、大分片处理方案

  • 1:删除非必要索引DELETE index_name
  • 2:删除大分片索引中的非必要数据,通过POST index/delete_by_query删除部分数据,可能存在问题数据量大删除慢
  • 3:使用_split索引进行拆分或者reindex进行索引重建都可以。
  • 4:解决方案1-reindex重建索引。重建索引可以对mapping进行重新设置,reindex必须提前配置mapping、分片计数、副本等。
    1、post设置mapping
    2、reindex方案参数确认
POST
{
  "source": {
    "index": "old_index",
	"size":1000   //可选,每次批量提交1000个,可以提高效率,建议每次提交5-15M的数据
  },
  "dest": {
    "index": "new_index"
  }
  • 5:解决方案2-split拆分分片。和reindex区别是更适合mapping没有改变时。split时分片数必须是原索引的整倍数
    1、新建所以并设置为只读索引
PUT /my_source_index/_settings
{
  "settings": {
  "index.number_of_shards" : 1,
    "index.blocks.write": true 
  }
}

2、split并设置别名。
POST my_source_index/_split/my_target_index { "settings": { "index.number_of_shards": 5 }, "aliases": { //aliases 创建别名 "my_search_indices": {} } }

2:实战记录

2.1:es写入异常,写入缓慢

性能记录:单台服务器可以达到8000/s的写入量
但是在集群异常时会急剧下降,报es_rejected_execution_exception或者超时

问题1:某台服务器的es进程重启会导致分片relocatiing迁移,会写入异常

问题2:整个集群的分片数或者单个索引的分片数
控制集群的分片数控制5W左右,不要太多,我们12w左右时出现过写入异常,降低分片到6W左右写入恢复
控制索引的分片数:600以下

2.2:es的节点个数规划

<=3个时,建议master和data节点一起部署
建议>=3个节点