垃圾回收

关于垃圾回收的详细信息

垃圾收集的必要性

  • 当用户删除文档时,Redis 仅在全局文档表中将其标记为已删除,而不是直接删除它们。这样做是为了提高效率。根据文档的长度,删除可能是一个耗时的操作。
  • 这意味着不再为已删除的文档分配内部数字ID。在遍历索引时,会检查是否已删除。
  • 所有属于已删除文档ID的反向索引条目都是垃圾。
  • 更新文档基本上与删除它然后使用新的增量内部ID再次添加它相同。不执行差异比较,索引是追加的,因此ID保持增量,更新速度快。

以上所有内容意味着,如果有大量的更新和删除操作,我们的倒排索引中的很大一部分将变成垃圾,既会减慢速度,又会消耗不必要的内存。

您希望优化索引,但也不想干扰正常操作。这意味着优化或垃圾回收应该是一个非侵入性的后台进程。它只需要在足够长的时间内比删除速率更快,这样您就不会产生比能收集的更多的垃圾。

垃圾回收单术语索引

单术语倒排索引是一个由多个块组成的数组,每个块包含一个编码的记录列表;例如,文档ID增量加上根据索引编码方案的其他数据。当这些记录中的一些引用已删除的文档时,这被称为垃圾。

算法很简单:

  1. 为每个块创建一个读取器和写入器。
  2. 逐个读取每个块的记录。
  3. 如果没有记录无效,则不执行任何操作。
  4. 当发现垃圾记录时,读取器会前进,但写入器不会。
  5. 当发现至少一个垃圾记录时,接下来的记录会被编码到写入器,并重新计算增量。

伪代码:

foreach index_block as block:
   
   reader = new_reader(block)
   writer = new_write(block)
   garbage = 0
   while not reader.end():
        record = reader.decode_next()
        if record.is_valid():
            if garbage != 0:
                # Write the record at the writer's tip with a newly calculated delta
                writer.write_record(record)
            else:
                writer.advance(record.length)
        else:
            garbage += record.length

数字索引上的垃圾回收

数值索引是一种倒排索引树,具有特殊的编码方式(docId delta, value)。这意味着可以对它们应用相同的算法,只需遍历树中的每个倒排索引对象。

FORK GC

关于FORK GC的信息可以在这个博客中找到。

自v1.6版本以来,FORK GC已成为默认的GC策略,并且在清理索引和不降低查询和索引性能方面表现出色,即使对于非常密集的写入用例也是如此。

RATE THIS PAGE
Back to top ↑