欢迎光临
我们一直在努力

如何通过物理删除与软删除机制优化 ES 索引的数据清理效率

作为Elasticsearch(ES)的资深用户,我们深知数据的删除操作并非简单的“一删了之”。标准的物理删除操作会在ES内部留下“tombstone”(删除标记),这些标记只有在后续的段合并(Segment Merge)过程中才会被清理,这会消耗大量的I/O和CPU资源,尤其是在高频删除的场景下,可能导致集群性能急剧下降。为了解决这一问题,我们可以采用软删除(Soft Delete)定期物理清理相结合的策略。

1. 理解ES的物理删除机制

当我们执行一个标准的删除请求(如DELETE /index/_doc/id)时,ES并不会立即从磁盘上移除数据。它会在倒排索引中标记该文档为已删除。直到Lucene进行段合并时,这些被标记的文档才会被真正物理移除。如果删除操作过于频繁,可能会导致:

  1. 索引大小(磁盘空间)并不会立即减小。
  2. 查询效率降低(需要跳过被标记的文档)。
  3. 段合并任务加重,影响写入和查询性能。

2. 实施软删除(逻辑删除)

软删除是通过在文档中添加一个状态字段来实现的,它不会触发ES底层的删除标记和段合并操作。这是优化高频删除场景的关键。

步骤 2.1:定义软删除字段

我们在索引映射中添加一个布尔字段,例如 is_deleted

PUT /my_data_index
{
  "mappings": {
    "properties": {
      "content": { "type": "text" },
      "created_at": { "type": "date" },
      "is_deleted": { "type": "boolean" }
    }
  }
}

步骤 2.2:执行软删除操作

当用户或系统请求删除文档时,我们不使用 DELETE API,而是使用 UPDATE API来更新 is_deleted 字段。

# 假设文档ID为1
POST /my_data_index/_update/1
{
  "doc": {
    "is_deleted": true
  }
}

步骤 2.3:修改查询逻辑

所有的查询请求都必须排除掉 is_deleted: true 的文档。这确保了业务层看不到已删除数据。

GET /my_data_index/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "term": { "is_deleted": true }
        }
      ]
    }
  }
}

软删除的优势: 快速,不会立即产生ES段合并开销;保留了数据审计轨迹;容易实现数据回滚。

3. 定期执行物理清理:优化数据释放

虽然软删除避免了即时性能冲击,但长期累积的软删除数据会浪费磁盘空间和查询资源。因此,我们需要定期(例如每天凌晨或每周一次)对这些标记为删除的数据进行批量物理清理。

我们使用高效的 _delete_by_query API来批量删除所有 is_deleted: true 的文档。

物理清理操作示例

POST /my_data_index/_delete_by_query
{
  "query": {
    "term": {
      "is_deleted": true
    }
  },
  "conflicts": "proceed"
}

建议和优化:

  1. 控制并发: 如果数据量巨大,可以使用 slices 参数将任务切片,以避免长时间占用ES资源。
  2. 流量控制: 使用 requests_per_second 参数限制删除速度,避免对实时查询产生太大影响。
  3. 段合并控制: 如果物理删除后索引文件大小变化巨大,ES可能会自动触发段合并。可以考虑在低峰期手动执行 forcemerge (如果索引是只读的,且数据量适中) 来控制合并时机,进一步释放磁盘空间。

通过将频繁的业务删除转换为轻量级的软删除,并将高开销的物理删除操作集中到系统低谷期进行批量处理,可以显著提高Elasticsearch索引的数据清理效率和集群的整体稳定性。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » 如何通过物理删除与软删除机制优化 ES 索引的数据清理效率
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址