soft-delete 可能导致 write queue 持续积压的问题
背景
Elasticsearch 7.7.0 之前的版本,对于以 update 方式写入的场景来说,存在 refresh 极慢的问题,很容易导致写入队列积压,自从 #52146 、#9228修复该问题后,soft-delete 看上去已经没有风险,然而坑比想象的要多,今天分享一下遇到的新情况-数据 balance 可能导致写入队列积压。
问题表现
write 队列持续积压,_cat/shards 可以看到问题索引的某个分片大小远远大于其他分片。当 move 主分片,增加副本,move 副分片,如果持续时间较长,可以复现此问题,主分片所在节点 write 队列持续积压。
问题分析
先看下发生积压时的火焰图,numDeletesToMerge函数的占比约 40%:
jstack可以看到 write 线程因numDeletesToMerge调用阻塞:
由于触发 findMerges 的 updatePendingMerges 是 synchronized方法,因此 numDeletesToMerge函数是串行的,该函数用于返回某个特定的段中已删除的 doc 数量,在SoftDeletesRetentionMergePolicy中他需要减去被软删除的,还在保留租约内的 doc 数。他使用SoftDeletesRetentionMergePolicy的 query去查询还在租约内的已被软删除的的 doc,然后遍历命中的 doc,去 liveDocs 中进行确认,如果已经 liveDocs 中为 0 则减1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public int numDeletesToMerge(SegmentCommitInfo info, int delCount, IOSupplier<CodecReader> readerSupplier) throws IOException { final int numDeletesToMerge = super.numDeletesToMerge(info, delCount, readerSupplier); if (numDeletesToMerge != 0 && info.getSoftDelCount() > 0) { final CodecReader reader = readerSupplier.get(); if (reader.getLiveDocs() != null) { BooleanQuery.Builder builder = new BooleanQuery.Builder(); builder.add(new DocValuesFieldExistsQuery(field), BooleanClause.Occur.FILTER); builder.add(retentionQuerySupplier.get(), BooleanClause.Occur.FILTER); Scorer scorer = getScorer(builder.build(), FilterCodecReader.wrapLiveDocs(reader, null, reader.maxDoc())); if (scorer != null) { DocIdSetIterator iterator = scorer.iterator(); Bits liveDocs = reader.getLiveDocs(); int numDeletedDocs = reader.numDeletedDocs(); while (iterator.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { if (liveDocs.get(iterator.docID()) == false) { numDeletedDocs--; } } } } } return numDeletesToMerge; } |
因此,当 query 命中数据量特别多的时候,其iterator.nextDoc() 过程会执行很慢。在发生积压的时候,采样 1 分钟的时间周期内,while循环的时间占用达到 30-50 秒
解决方式
- 临时解决方式,降低 index.soft_deletes.retention_lease.period 时间,可以快速消除症状。
- 彻底解决方式,早在 2018 年的时候 es 社区就有过方案 #35594,为numDeletesToMerge函数增加 cache,因为段内被删除的数量大多时候总是固定的,减去软删除的数量并不要求总是实时进行,但这个 PR 当时并没有 merge,因为在当时的版本中,softdelete 的其他问题更显严重。
截止目前的版本 7.14 为止改问题仍然存在,不过正在推进社区重新考虑合并上述 PR。
参考
https://www.amazingkoala.com.cn/Lucene/Index/2020/0709/153.html
(转载请注明作者和出处 easyice.cn ,请勿用于任何商业用途)
One thought on “soft-delete 可能导致 write queue 持续积压的问题”
This valuable opinion