Elasticsearch线上问题

2023年 8月 16日 60.4k 0

Elasticsearch线上问题

WangScaler: 一个用心创作的作者。

声明:才疏学浅,如有错误,恳请指正。

一、429拒绝访问

1、错误信息

1 ERROR:root:TransportError(429, 'circuit_breaking_exception', '[parent] Data too large, data for [] would be [2042405264/1.9gb], which is larger than the limit of [2040109465/1.8gb], real usage: [2042404224/1.9gb], new bytes reserved: [1040/1kb], usages [request=0/0b, fielddata=0/0b, in_flight_requests=1040/1kb, model_inference=0/0b, eql_sequence=0/0b, accounting=113390388/108.1mb]')

我们ES的内存设置的是2G。从图上可以看出,内存已经不够用了。我们在Elasticsearch集群降级为单节点已经介绍了内存的设置范围以及原因,有兴趣的可以看看。

2、429状态码的含义

我们知道我们对ES的访问是通过HTTP请求,所以首先要知道429状态码在HTTP请求中代表的含义。429状态码表示Too Many Requests即当前客户端已经在给定的时间内发送了太多的请求。通俗的理解就是在单位时间内,我们发送了大量的请求到ES,ES处理不了这么多请求,就发生了熔断,来保护ES。

3、根本原因

ES的请求处理不了那么多,也就是性能上低于我们的正常业务。从第一步我们也可以看出我们内存不够用了,其次很可能是用于处理请求的线程池资源数受限。

4、解决方案

  • ①增大单个节点的内存,或者增大节点数量。道理很简单,增大单个节点的内存,即增大了单个节点的处理能力。而增大节点的数量,就会将请求分散到更多的节点,减少了每个节点的压力。不过这种方案往往在现实中不好实现,为什么?因为增大配置就需要钱,哈哈,为公司节省才能给老板买新车,能省就省。

  • ②增加线程池线程数量。可以通过GET /_nodes/节点/settings/ 查看thread_pool线程池的配置,但是增加配置,势必需要更多的内存,我们如果面临内存不足的痛楚,可能单纯的增大会带来相反的效果。

  • ③从根本上不好解决的问题,那么只能从业务上想办法,首先找到业务上大批量请求的原因。比如我的是设备数据入库,而数据都是同一时间点上传,而我入库之前是先查看索引是否存在,不在的话,手动创建索引并指定mapping,因为指定了mapping才方便后续的聚合分析,所以必须保证索引是我们手动创建的,而不是自动生成的。

    • 减少批量请求。假设有1000设备数据上来,就需要1000个查看索引的请求,1000个写入数据的请求。负载量确实很大,向我们的索引其实只需要查看一次就已经确定索引是否存在了,可以将已经存在的索引缓存到redis,减少一半的请求。
    • 以时间换安全。假设数据每个设备每分钟上传一条,我们如果对数据实时性要求不高的话,可以延长调度数据的时间,假如每小时调度一把,这样一个小时一个设备只有一个bulk请求,每个请求60条数据。假设10000个设备,每调度100个设备休眠5s。只需要500s即不到9分钟。也就是每一小时拿出9分钟调度所有设备的数据,且中间有休眠,来缓解ES的压力

5、其他

之前查阅资料,有说field data的缓存不够用,应该设置为JVM内存的40%或更小

PUT /_cluster/settings" -H 'Content-Type: application/json' -d '{ "persistent" : { "indices.breaker.fielddata.limit" : "40%" } }'

或者修改配置文件config/elasticsearch.yml

indices.fielddata.cache.size:  40%

第二种需要重启生效

不过text类型的字段在聚合、排序或者脚本访问时才会使用fielddata作为查询时内存数据结构,我的数据都是double类型的,显然于此无关。如果你的是text类型的数据,则需要避免text类型的字段上使用firlddata,默认情况下,es是禁用的。

如果你必须开启的话,可以清除下缓存

POST _cache/clear?fielddata=true

二、分片不够

1、错误信息

Failed: 1: this action would add [1] total shards, but this cluster currently has [1000]/[1000] maximum shards open;

2、根本原因

从上一步,很明显可以看出1000个分片已经达到最大了,也就是ES默认的最大分片数是1000个,我们按照一个节点3个分片算,也就是1000/3=333个索引。那么我们只能创建333个索引,然而在现实中这远远不够的,所以需要增大这个配置。

3、解决方案

  • 临时生效curl -XPUT -H "Content-Type:application/json" http://127.0.0.1:9200/_cluster/settings -d '{ "transient": { "cluster": { "max_shards_per_node": 10000 } } }'

  • 永久生效curl -XPUT -H "Content-Type:application/json" http://127.0.0.1:9200/_cluster/settings -d '{ "persistent": { "cluster": { "max_shards_per_node": 10000 } } }'

  • 配置文件永久生效。修改elasticsearch.yml

    cluster.max_shards_per_node: 10000
    

    需要重启。

指定大小根据业务量自行调整。

三、参考资料

  • 1、修复 Elasticsearch 集群的常见错误和问题
  • 2、elasticsearch 7.4 出现circuit_breaking_exception异常
  • 3、Elasticsearch集群降级为单节点

来都来了,点个赞再走呗!

关注WangScaler,祝你升职、加薪、不提桶!

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论