一、前言|
ES作为现今最流行的搜索存储库,我们需要定期去清理ES集群的数据以保证集群处在一个最佳负载状态,那么如何去删除这些数据呢,我们今天来介绍一种比较常见的通过Delete By Query的方式去删除索引中的数据。
二、Delete By Query API 介绍
怎么理解这个API呢?实际是批量删除数据的意思 功能:根据特定的查询条件对ES相关索引中某些特定的文档进行批量删除。
POST index_name/_delete_by_query
{
"query": { //这些是自定义查询条件,根据查询条件去批量删除
"match": {//请求体跟Search API是一样的
"message": "some message"
}
}
}
Delete By Query 删除原理:
Delete_by_query并不是真正意义上物理文档删除,而是只是版本变化并且对文档增加了删除标记。当我们再次搜索的时候,会搜索全部然后过滤掉有删除标记的文档。因此,该索引所占的空间并不会随着该API的操作磁盘空间会马上释放掉,只有等到下一次段合并的时候才真正被物理删除,这个时候磁盘空间才会释放。相反,在被查询到的文档标记删除过程同样需要占用磁盘空间,这个时候,你会发现触发该API操作的时候磁盘不但没有被释放,反而磁盘使用率上升了。
使用Delete By Query 删除API注意事项:
1, 一般生产环境中,使用该API操作的索引都很大,文档都是千万甚至数亿级别。索引大小在几百G甚至几个T,因此,这个操作建议在业务低峰期或者晚上进行操作,因为大数据量情况下删除的需要消耗较多的i/o CPU 资源,容易对生产集群造成影响。
2,在删除过程中要确定集群磁盘有一定的余量,因为标记删除需要占用磁盘空间。如果磁盘空间不够,这个操作的失败率还是很大的。
3,Delete By Query有很多配置参数,这里不详解,具体可以参考文档:
https://www.elastic.co/guide/en/elasticsearch/reference/7.2/docs-delete-by-query.html
三、段合并 --> 强制段合并 --> Force merge 《高资源消耗动作》
由于自动刷新流程每秒会创建一个新的段 ,这样会导致短时间内的段数量暴增。而段数目太多会带来较大的麻烦。 每一个段都会消耗文件句柄、内存和cpu运行周期。更重要的是,每个搜索请求都必须轮流检查每个段;所以段越多,搜索也就越慢。Elasticsearch通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。段合并的时候会将那些旧的已删除文档从文件系统中清除。被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中。启动段合并不需要你做任何事。进行索引和搜索时会自动进行。
Elasticseach会有后台线程根据Lucene的合并规则定期进行segment merging合并操作,一般不需要用户担心或者采取任何行动。被删除的文档在segment合并时,才会被真正删除掉。在此之前,它仍然会占用着JVM heap和操作系统的文件cache、磁盘等资源。在某些特定情况下,我们需要强制Elasticsearch进行segment merging,已释放其占用的大量系统、磁盘等资源。具体操作如下:
POST /index_name/_forcemerge
_forcemerge 命令可强制进行segment合并,并删除所有标记为删除的文档。Segment merging要消耗CPU,以及大量的I/O资源,所以一定要在你的ElasticSearch集群处于维护窗口期间,并且有足够的I/O空间的(如:SSD)的条件下进行;否则很可能造成集群崩溃和数据丢失.<这个非常重要>
_forcemergeAPI 有几个常用的参数:
max_num_segments 是表示将某个索引的每个分片强制合并为几个段的意思。
only_expunge_deletes 是表示仅将标记删除为文档的进行强制合并物理删除,不进行其它合并操作。
比如下面的API,表示:
POST /index_name/_forcemerge?max_num_segments=1
上面API的意思表示合并索引中的每个分片为一个单独的段,可以先设置大一点,10-5-1,一点一点慢慢降到1。一般推荐为1.
或者如下操作:
POST /index_name/_forcemerge?max_num_segments=1&only_expunge_deletes=true
四、Delete_by_query 、Forcemerge 数据操作实践
案例背景:
客户集群的索引没有预先规划大小,导致索引特别大,删除数据删除索引的形式进行,只能在原来的索引上进行数据删除操作。
实际情况如下图所示:
在保证业务低峰期,我们进行delete_by_query操作,如下:
POST /index-name/_delete_by_query?slices=auto&conflicts=proceed&wait_for_completion=false
{ //多线程并发删除满足查询条件的数据
"query": {
"bool": {
"filter": {
"bool": {
"must_not": [
{
"term": { //查询条件,可以自定义
"action": "XXXXXXX"
}
},
{
"exists": {
"field": "XXXXXXXX" //查询条件,可以自定义
}
}
]
}
}
}
}
}
执行如上程序,会生成一个TaskID,我们可以通过这个taskID去查看这个进程。
执行上面的API,后面的工作直接交给ES进程去调用处理,这个过程根据数据大小来定。接着,我们再执行强制合并,快速删除数据,释放系统资源,我们需要强制合并。如下操作:
POST /index_name/_forcemerge?max_num_segments=1&only_expunge_deletes=true
or
POST /index_name/_forcemerge?max_num_segments=1
执行上面2个步骤,整个流程就基本操作完毕,其它工作交给系统自动完成。时间待定。期间你会发现,磁盘空间会有一个反复变化的过程,磁盘使用率会先增长,然后在删除释放空间这样一个过程。这个过程无需紧张,都是正常现象。最终,流程执行完毕后会形成如下结果:
以上就是整个批量删除和强制段合并操作实列。
五、总结
ES删除数据共有如下几种方式:
1,删除指定文档:指定索引–>类型–>id的方式对文档进行删除
DELETE /index/type/1
2,批量删除:Delete_by_query 特点:麻烦,注意事项挺多,专业度高。
3,删除索引:Delete Index 特点:干净快速,一步到位。
4,Delete_by_query,定时任务,参考下文: https://blog.csdn.net/geekswg/article/details/107097322
5,本文鸣谢以下链接信息:
https://blog.csdn.net/u013200380/article/details/109163812
https://www.elastic.co/guide/en/elasticsearch/reference/7.2/indices-forcemerge.html#indices-forcemerge
https://www.jianshu.com/p/60a6ad164035