Elasticsearch 7.4的 soft-deletes 是个什么鬼

Elasticsearch 7.4的 soft-deletes 是个什么鬼

新概念

从 Elasticsearch 7.4 开始,peer-recovery(副分片的恢复)不再依赖从主分片拉取 translog。在 6.0-7.3的版本中,Elasticsearch默认会保留512M 或12小时的 translog 用于 peer-recovery,副分片进行恢复时,只要待获取的差异数据是在 translog 所保留的数据范围的,就可以只从 trasnlog 复制差异的部分数据,而不用拖取整个分片。

现在,追踪主分片上的操作历史可以通过 Lucene 的新特性“软删除”来实现,不再依赖 translog。CCR 也会使用这个特性。与 Lucene 中原有的“删除”(或者说硬删除)相比,原有的“删除”会做一些标记, doc 在磁盘中还存在。然后在segment merge 的时候真正的删除这些 doc。现在既然要从 Lucene 获取操作历史,就要避免这种情况,让被删除的数据在 merge 时不被影响,所以“软删除”的概念其实和原来差不多:

  • 还是标记删除,让文档看上去被删除了,用户查询不到,但磁盘上存在
  • merge 操作不清理被”软删除“的 doc
  • 在一定时间后,允许 merge 操作清理被”软删除“的 doc,实现保留一定期限的历史,而非无限期保留。

如果单单从效果来看,软删除和硬删除的区别就是 merge 之后,被软删除的 doc会被保留。而后通过一些其他的接口可以读到被软删除的文档。

Elasticsearch 的软删除原理

soft-deletes 是 Lucene 中实现的特性,本质上是增加一个额外的字段代表doc是否被软删除,执行删除操作的时候,新增了一个 doc,在这个 doc 中将代表软删除的字段标记为1。

Lucene 的软删除过程

我们用 Lucene 的 API 演示一下删除过程,首先初始化 IndexWriter,并指定哪个字段代表软删除的字段:

然后新增一个 doc,docId 为1,这与之前的使用方式没有什么区别:

接着用软删除的方式删除他,实际就是创建一个新的 doc,将docId设置为要删除的 docId,并将 softDelete 字段值设置为1:

writer.softUpdateDocument完成了文档的软删除过程,接下来用不同的 reader 就可以读取到,或者过滤掉被软删除的文档。例如搜索分片时应该过滤掉被软删除的 doc,而 recovery 的时候需要读取所有操作历史,包括被软删除的文档。

Elasticsearch 中关于软删除的变更

现在看一下Elasticsearch中应用软删除之后,涉及到 Lucene读写API 的变更。

删除文档时

在 deleteInLucene 函数删除文档的时候,之前的硬删除使用Lucene deleteDocuments删除文档:

使用软删除方式时,实现改为:

与我们上一个演示 Lucene 中软删除的例子类似。

搜索时

与之前的读取方式相比没有变化

创建的Context为DefaultSearchContext,其中searcher中的 reader 为ElasticsearchDirectoryReader,这个 reader 不会读取到被软删除的文档。

恢复时

peer-recovery 的时候RecoverySourceHandler#recoverToTarget函数中,获取 translog 快照:

快照最终通过 LuceneChangesSnapshot类创建,其中会初始化一个indexSearcher负责读取,他的初始化方式如下:

通过 Lucene.wrapAllDocsLive 返回一个IndexReader,这种方式创建的 reader可以获取到包括被软删除的所有的 doc。

目前存在的问题

软删除也带来了一些负面影响。截止目前的版本为止(7.5.2),对于 update 操作,他导致 refresh 变得很慢。以下面这个 UT 为例:

上面这个10W 条 doc 的 update 之后,engine.refresh函数的运行在我的测试环境中消耗了100多秒的时间。

refresh慢导致了另外一个问题,他确实足够慢,以至于很可能会小于数据写入速度,indexing buffer 的内存来不及 refresh 到磁盘中。如果对节点执行 update 压测,你会发现indexWriter会暴涨到index_buffer_size配置的阈值,并持续占据这些内存。

当 indexWriter大于index_buffer_size配置的阈值,Elasticsearch 会对写入操作执行反压,降低分片的写入速度,被反压的分片除了在执行 update 的分片,其他索引的分片也可能会受影响,因此可能会导致整体写入速度下降。

总结

soft-deletes 本质上就是加了一个额外的字段表示文档被删除了,然后在通过一些其他 api 将soft-deletes的 doc 读出来。但是目前(v7.5.2)为止对 update 的影响比较大,如果你已经升级到这个版本,可以在写入请求中加上 ?refresh 参数,让每个请求都被 refresh,可以避免对indexWriter内存及后续的影响。

参考

https://www.elastic.co/cn/blog/follow-the-leader-an-introduction-to-cross-cluster-replication-in-elasticsearch

https://www.elastic.co/guide/en/elasticsearch/reference/current/release-notes-7.4.0.html

https://www.elastic.co/guide/en/elasticsearch/reference/7.x/index-modules-history-retention.html

(转载请注明作者和出处 easyice.cn ,请勿用于任何商业用途)

1 Star2 Stars3 Stars4 Stars5 Stars (欢迎评分)
Loading...

5 thoughts on “Elasticsearch 7.4的 soft-deletes 是个什么鬼

  1. 你好,没理解7.4后不通过translog replay 操作记录,而是通过 Lucene 的新特性“软删除”来实现。这个区别是什么呢?我看源码还是通过translog读取操作记录

cztchoice进行回复 取消回复

邮箱地址不会被公开。 必填项已用*标注