Milvus 数据段合并机制

​我们在《Milvus在大规模向量检索场景下的数据管理》这篇文章说过,当向量数据不断地进入 Milvus 时,系统后台会持续地将插入缓冲区中的数据写入磁盘,形成很多小文件。我们称这些文件为数据段。大量零碎的数据段有两个明显缺点:

  • 不利于元数据管理,对 SQLite/MySQL 的访问频繁

  • 索引过于分散,影响查询的性能

因此 Milvus 后台落盘任务会不断地把这些小数据段合并成大数据段,直到合并后的数据段大小超过 index_file_size(默认 1024MB )这个阈值。

 

| 旧版本合并机制的缺点

在 0.9.0 版本以前,数据段的合并策略是简单粗暴的:先从元数据拿到一批需要被合并的数据段,然后循环遍历合并。如下图所示:

 

假设拿到 7 个数据段:

1. 从第一个开始合并到第三个,segment_8 已经超过 1024MB 的大小,就停止对 segment_8 的合并;

2. 接着从第四个合并到第六个,合并为 segment_9;

3. 合并完成后将前六个数据段标记为软删除,最终剩下三个数据段:segment_7,segment_8,segment_9。

这种合并机制有一个很大的缺点:占用过多的磁盘空间。

大规模向量检索场景下的数据管理(下篇)这篇文章介绍过,数据段的删除是分为两个阶段的:软删除和硬删除。当数据段被标记为软删除后,并不会立刻从磁盘中清理掉,而是会保留一段时间,直到后台清理线程将其硬删除,才会被清理掉。因此,在某些特定场景下,这种合并机制会造成巨大的磁盘空间浪费。

假设有一个 256 维的集合,index_file_size 为 1024M, 每条向量的大小为 1KB。该集合中已存在一个 100MB 的数据段,客户端以每秒 1 条的频率插入向量。系统配置的 auto_flush_interval 为 1 秒,也就是每秒写一次磁盘。我们来看插入三次过程中后台的合并行为:

 

经过三次操作后,数据合并为segment_7,大小为 100MB+3KB。而其他六个数据段被标记为软删除状态,但它们的文件仍然在存在于硬盘中,这些文件的总大小超过了400MB。在三次插入以及合并过程中,写入磁盘的数据量为300MB+9KB。可以看到,余留的文件大小是实际数据量(100MB)的4倍,磁盘写入的数据量是实际数据量的3倍。我们称这种现象为“写放大”,根本原因是因为被合并的数据段的大小差距过大。

 

|  0.9.x版本的合并策略

 

1)层级合并策略

为了缓解“写放大”问题,我们在 0.9.0 中进行了改进。在介绍新的策略之前,我们先来玩一个游戏,游戏名叫做 “2048”,可能很多人都玩过,没玩过的可以到这里:https://2048game.com/

玩过的都知道,这游戏里,数字 2 只可以跟数字 2 合并,但不能跟其他数字合并。同样的,数字 4 只能跟数字 4 合并,数字 8 只能跟数字 8 合并,以此类推。

新的合并策略将数据段按大小划分为几层:0MB~4MB,4MB~16MB,16MB~64MB,64MB~256MB,大于 1GB 的归为一层。合并的时候,仅对层内数据段进行合并,这样就避免了小数据段和大数据段的合并,减少磁盘写入量,减少过大的临时文件。那么我们来看一下在上一节的场景下,使用新的合并策略后,磁盘的使用量有没有缓解:

可以看到,三次插入和合并操作完成后,数据合并为 segment_6,但 segment_1 没有参与合并,其他四个数据段被标记为软删除。磁盘占用量为 100MB+8KB,磁盘写入数据量为 8KB。基本缓解了“写放大”问题。

 

2)适配合并策略

上面这种分层合并策略是在落盘任务完成之后触发的,我们可以看到对于在不同层级的数据段没有得到合并(比如上面场景中的 segment_1 和 segment_6)。在对集合建索引之前,要尽可能地把数据段合并到 index_file_size 指定的大小,这就需要另一种合并策略。适配合并策略就是用来做这个事情的,实际上就是按数据段大小往 index_file_size 上“凑”。比如,对于下面一组数据段,index_file_size 为 1024MB,适配合并策略的效果如下:

这里最终得到了 segment_8、segment_9、segment_10 三个数据段,前两个数据段的大小和 index_file_size 很接近。

 

| 新的合并策略的触发条件

合并操作触发的时机有以下几个:

  • Milvus 服务启动时(适配合并策略)

  • 落盘任务完成之后(层级合并策略)

  • 建索引之前(适配合并策略)

  • 删除索引之后(适配合并策略)

由于“写放大”问题主要出现在持续插入数据以及落盘过程中,因此,仅在落盘任务完成时使用了层级合并策略,其他几个都使用了适配合并策略。

 

 

 

| 欢迎加入 Milvus 社区

 

github.com/milvus-io/milvus | 源码

milvus.io | 官网

milvusio.slack.com | Slack 社区

zhihu.com/org/zilliz-11/columns | 知乎

zilliz.blog.csdn.net | CSDN 博客

space.bilibili.com/478166626 | Bilibili

 

实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值