博主有话说:该博文根据实际案例编写,在编写过程中将敏感信息进行替换,可能存在矛盾的地方,望见谅
1 错误详情
[type=circuit_breaking_exception, reason=[parent] Data too large, data for [<http_request>] would be [125643918/119.8mb], which is larger than the limit of [90832896/86.6mb], real usage: [125639936/119.8mb], new bytes reserved: [3982/3.8kb], usages [request=0/0b, fielddata=0/0b, in_flight_requests=3982/3.8kb, accounting=15713/15.3kb]] ElasticsearchStatusException[Elasticsearch exception [type=circuit_breaking_exception, reason=[parent] Data too large, data for [<http_request>] would be [125643918/119.8mb],
在这里找到了3个数值
Data too large, data for [] would be [125643918/119.8mb] 这个就是上限内存(缺省是它是ES最大内存的95%)
real usage: [125639936/119.8mb], ES已经使用的内存
new bytes reserved: [3982/3.8kb] 本次查询需要的内存
2 方案一:增加es的内存
2.1 增加es的内存
编辑elasticsearch配置路径下的jvm.options文件,修改总堆空间的初始大小和总堆空间的最大大小,重启es应用即可
可以根据剩余内存大小情况增加es内存
注:初始值和最大值应当被设置为相同的值
2.2 方案分析
该方案简单粗暴,但是要考虑服务器性能。增加es内存的同时,要考虑到对其它应用的影响,不能增加太高,比如增加到2~3G。而且随着时间的推进,es数据量的增加,可能还会出现此问题,无法从根本上解决问题,可以考虑与其他方案双管齐下。
3 方案二:删除es数据
3.1 删除所有文档
构建一个匹配所有文档的查询,并使用DELETE BY QUERY API来删除它们。这样,索引的结构会保留,但其中的所有数据都将被删除。
POST /my_index/_delete_by_query
{"query": {"match_all": {}}
}
curl -uelastic:elastic_pwd -H "Content-Type:application/json" -XPOST http://127.0.0.1:6200/my_index/_delete_by_query -d '{"query": {"match_all": {}}
}'
3.2 创建空索引,删除旧索引
创建一个新的具有相同结构但没有任何数据的空索引,然后根据需要删除旧索引,并将新索引重命名为旧索引的名称。
3.2.1 创建具有相同结构的空索引
创建一个新的索引,可以通过发送PUT请求到新索引,并在请求体中包含映射定义来实现。
PUT /new_index
{"mappings": {"properties": {"field1": { "type": "text" },"field2": { "type": "keyword" },// ... 其他字段定义,根据从旧索引获取的映射来填充 ...}}
}
# 创建名为 new-index 的索引
curl -uelastic:elastic_pwd -H "Content-Type:application/json" -XPUT http://127.0.0.1:6200/new_index -d @/data/my-index.txt
以上命令需要知道索引的结构,如果不知道,可以使用以下命令查看旧索引结构
3.2.2 获取旧索引结构
通过发送GET请求到旧索引的_mapping
端点来实现:
GET /old_index/_mapping
curl -uelastic:elastic_pwd -XGET http://127.0.0.1:6200/my_index/_mapping
3.2.3 删除旧索引
使用DELETE
请求来删除索引。
DELETE /my_index
curl -uelastic:elastic_pwd -XDELETE http://127.0.0.1:6200/my_index
3.2.4 新索引重命名
为了使应用程序能够无缝地从旧索引切换到新索引,你可以使用Elasticsearch的别名功能。通过为新索引创建一个与旧索引同名的别名,可以让应用程序继续使用相同的索引名称来访问数据,而实际上是在访问新的索引。这样,从应用程序的角度来看,就实现了索引的“重命名”。
POST _aliases
{"actions": [{"add": {"index": "new_index","alias": "my_index"}}]
}
curl -u elastic:elastic_pwd -H "Content-Type:application/json" -XPOST http://127.0.0.1:6200/_aliases -d '
{"actions": [{"add": {"alias": "my_index","index": "new_index"}}]
}'
3.3 方案分析
删除所有文档中DELETE BY QUERY操作可能会消耗一定的时间和资源,特别是在大型索引上。确保你的Elasticsearch集群能够处理这个操作,并考虑在低峰时段执行它,且无法恢复数据。
创建空索引删除旧索引,相对来说消耗的时间和资源较少,该案例没有提前设置索引别名,如果设置有索引别名,完全可以不用删除旧索引,方案可能会更好(参考方案五)
删除数据,并不会立即释放存储和内存,需要进行es数据的 segment合并操作,而这个操作特别消耗服务器资源(cpu和内存),数据越大消耗越大,数据大的情况下甚至容易造成进程卡死,数据量越大,做起来风险就越大
4 方案三:保留最近一部分es数据
此方案是在方案二的基础上进行的优化,根据客户要求,可以将es数据进行删除操作,但是最好可以保留最近30-60天的数据
4.1 条件删除文档
构建一个匹配60天前文档的查询,并使用DELETE BY QUERY API来删除它们。这样,索引的结构会保留,并且保留近60天的数据。
POST /my_index/_delete_by_query
{"query": {"range": {"@timestamp": {"gte" : "$date_start 00:00:00","lt" : "$date_end 00:00:00","format" : "yyyy-MM-dd HH:mm:ss"}}}
}
curl -uelastic:elastic_pwd -H "Content-Type:application/json" -XPOST http://127.0.0.1:6200/my_index/_delete_by_query -d '{"query": {"range": {"@timestamp": {"gte" : "$date_start 00:00:00","lt" : "$date_end 00:00:00","format" : "yyyy-MM-dd HH:mm:ss"}}}
}'
注:$date_start、$date_end为变量,可以自定义删除这两个日期之间的数据
4.2 创建空索引,同步近两个月的数据,删除旧索引
此方案是在方案二(3.2)的基础上添加步骤:新索引同步近两个月的数据
4.2.1 新索引同步近两个月的数据
注:此方法需要借助logstash应用
- 创建同步数据使用的logstash配置文件,命名为logstash.conf
input {elasticsearch {hosts => ["127.0.0.1:6200"] index => "my_index" user => "elastic" password => "elastic_pwd"size => 500scroll => "5m"docinfo => truequery => '{"query":{"range":{"@timestamp":{"gt":"2024-05-01 00:00:00"}}}}'}
}filter {
}output {elasticsearch {hosts => ["127.0.0.1:6200"]index => "new_index"user => "elastic" password => "elastic_pwd" }
}
- 启动一个logstash 进程,使用logstah.conf 配置(logstash目录按实际情况修改,http.port端口需要写一个未被占用的端口
/data/logstash-7.6.1/bin/logstash -f ./logstash.conf --path.data=./logstash_trans --http.port=6609
4.3 方案分析
条件删除文档中DELETE BY QUERY操作可能会消耗一定的时间和资源,特别是在大型索引上。确保你的Elasticsearch集群能够处理这个操作,并考虑在低峰时段执行它,且无法恢复数据。
同步数据耗时太长,可能无法实施(经初步估算,测试环境测试同步1.3G数据,耗时40-50分钟,每天数据量大概800M,同步一个月数据耗时太长)
5 方案四:定时删除es数据
5.1 定时删除es数据脚本
脚本文件重命名为del_es_data.sh
#!/bin/bash# 保留数据的天数
DEL_BEF_DAYS=60
# es服务器ip:端口
ES_HOST='127.0.0.1:6200'function main
{typeset date_end=`date +%Y-%m-%d -d "$DEL_BEF_DAYS days ago"`typeset date_start=`date -d "1 days ago $date_end" +%Y-%m-%d`echo "date_start: $date_start 00:00:00"echo "date_end: $date_end 00:00:00"curl -u elastic:elastic_pwd -X POST http://$ES_HOST/my_index/_delete_by_query -H "Content-type: application/json" -d '{"query": {"range": {"@timestamp": {"gte" : "$date_start 00:00:00","lt" : "$date_end 00:00:00","format" : "yyyy-MM-dd HH:mm:ss"}}}}'echo "######################## 删除完成 ########################"
}main "$@"
5.2 设置定时任务
输入以下命令:
crontab -e
在打开的页面输入定时任务(每天凌晨0点0分执行删除es数据脚本):
0 0 * * * /bin/del_es_data.sh
5.3 方案分析
单纯使用此方案无法解决问题,但可以保证es数据量不再增加,可以考虑与其他方案双管齐下。
6 定稿方案:增加es内存,使用新索引,定时删除es历史数据
通过对以上方案的优劣分析,最终制定定稿方案
6.1 增加es内存
参考2.1
编辑elasticsearch配置路径下的jvm.options文件,修改总堆空间的初始大小和总堆空间的最大大小,重启es应用即可
注:初始值和最大值应当被设置为相同的值
6.2 创建新索引
参考3.2.1
创建一个新的索引,可以通过发送PUT请求到新索引,并在请求体中包含映射定义来实现。
# 创建名为 new-index 的索引
curl -uelastic:elastic_pwd -H "Content-Type:application/json" -XPUT http://127.0.0.1:6200/new_index -d @/data/my-index.txt
以上命令需要知道索引的结构,如果不知道,可以使用以下命令查看旧索引结构(参考3.2.2)
curl -uelastic:elastic_pwd -XGET http://127.0.0.1:6200/my_index/_mapping
查看索引 (确认上面的新索引是否建立成功)
curl -uelastic:elastic_pwd http://127.0.0.1:6200/_cat/indices?v
6.3 删除旧索引别名(如果没有别名可跳过此步骤)
curl -uelastic:elastic_pwd -H "Content-Type:application/json" -XPOST http://127.0.0.1:6200/_aliases -d '
{"actions": [{"remove": {"alias": "my_index","index": "my_index-v1"}}]
}'
确认别名删除成功,确认返回值中 aliases字段的值为空。
curl -uelastic:elastic_pwd -XGET http://127.0.0.1:6200/my_index
6.4 删除旧索引(如果执行了6.3可跳过此步骤,保留历史数据)
参考3.2.3
使用DELETE
请求来删除索引。
curl -uelastic:elastic_pwd -XDELETE http://127.0.0.1:6200/my_index
6.5 创建新索引别名
参考3.2.4
curl -u elastic:elastic_pwd -H "Content-Type:application/json" -XPOST http://127.0.0.1:6200/_aliases -d '
{"actions": [{"add": {"alias": "my_index","index": "new_index"}}]
}'
确认别名创建成功,确认返回值中 aliases字段的值为my_index。
curl -u elastic:elastic_pwd -XGET http://127.0.0.1:6200/new_index
6.5 关闭旧索引(未删除旧索引时执行该步骤)
curl -u elastic:elastic_pwd -H "Content-Type:application/json" -XPOST http://127.0.0.1:6200/my_index/_close
注释:即使旧索引不再活跃,它仍然会占用磁盘空间和部分内存。这是因为Elasticsearch为了保持索引的可用性和快速检索能力,会保留索引的元数据和部分索引结构在内存中。此外,打开的文件句柄等资源也会被占用,直到索引被显式删除或关闭。
6.6 定时删除es数据
参考5 方案四
6.6.1 编写删除es数据脚本
脚本文件重命名为del_es_data.sh
#!/bin/bash# 保留数据的天数
DEL_BEF_DAYS=60
# es服务器ip:端口
ES_HOST='127.0.0.1:6200'function main
{typeset date_end=`date +%Y-%m-%d -d "$DEL_BEF_DAYS days ago"`typeset date_start=`date -d "1 days ago $date_end" +%Y-%m-%d`echo "date_start: $date_start 00:00:00"echo "date_end: $date_end 00:00:00"curl -u elastic:elastic_pwd -X POST http://$ES_HOST/my_index/_delete_by_query -H "Content-type: application/json" -d '{"query": {"range": {"@timestamp": {"gte" : "$date_start 00:00:00","lt" : "$date_end 00:00:00","format" : "yyyy-MM-dd HH:mm:ss"}}}}'echo "######################## 删除完成 ########################"
}main "$@"
6.6.2 设置定时任务
输入以下命令:
crontab -e
在打开的页面输入定时任务(每天凌晨0点0分执行删除es数据脚本):
0 0 * * * /bin/del_es_data.sh
6.7 方案分析
操作简单、无风险,只是变更后无法查看历史数据(回退后即可查看历史数据)
注:回退时需要打开旧索引
curl -u elastic:elastic_pwd -H "Content-Type:application/json" -XPOST http://127.0.0.1:6200/my_index/_open