专栏首页Reinvent Data ScienceMilvus 如何实现数据动态更新与查询

Milvus 如何实现数据动态更新与查询

在这篇文章,我们会主要描述 Milvus 里向量数据是如何被记录在内存中,以及这些记录以怎样的形式维护。

我们的设计目标主要有下面三点:

  1. 数据导入效率要高
  2. 数据导入后尽快可见
  3. 避免数据文件碎片化

因此,我们建立了插入数据的内存缓冲区(insert buffer),以减少磁盘随机 IO 和操作系统中上下文切换的次数,从而提升数据插入的性能。基于 MemTable 和 MemTableFile 的内存存储架构,能使我们更加方便的管理和序列化数据。将 buffer 的状态分为 Mutable 和 Immutable,能让数据持久化到磁盘的同时保持对外服务可用。

| 准备

当用户准备插入向量到 Milvus 时,首先需要创建一个 Collection(*Milvus 在0.7.0版本中将 Table 更名为 Collection)。Collection 是 Milvus 记录和搜索向量的最基本单位。每个 Collection 有一个独特的名字和一些可以被设置的属性,并且根据 Collection 的名字进行向量的插入或搜索。创建一个新的 Collection 时,Milvus 会在元数据里记录下这个 Collection 的信息。

| 数据的插入

当用户发出插入数据的请求时,数据经过序列化和反序列化,到达 Milvus server。数据这时候开始写入内存。内存写入大致分为下面几个步骤:

  1. 在 MemManager 中,找到或新创建与Collection 名字对应的 MemTable。每个 MemTable对应一个 Collection 在内存中的 buffer。
  2. 一个 MemTable 会包含一个或多个 MemTableFile。每当我们创建一个新的 MemTableFile,我们会同时在 Meta 中记录这个信息。我们将 MemTableFile 分为两种状态:Mutable 和 Immutable。当 MemTableFile 大小达到阈值,会变成 Immutable 状态。每个 Memtable 在任意时间只会存在一个 Mutable MemTableFile 可被写入。
  3. 每个 MemTableFile 的数据会最终以被设置的 index 类型的格式记录在内存里。MemTableFile 是在内存中管理数据的最基本单位。
  4. 任意时刻,插入数据的内存的占用量都不会超过预先设置的值(insert_buffer_size)。这是因为每一个插入数据的请求进来,MemManager 都可以很方便的计算到每个 MemTable 下包含的 MemTableFile 所占内存,然后根据当前内存协调插入请求。

通过 MemManager, MemTable 和 MemTableFile 多层级的架构,数据的插入可以更好地被管理和维护。当然,它们能做的远不止这些。

| 近实时查询

在 Milvus 里,从数据被记录在内存,到数据能被搜到,你最快只需要等待一秒。这整个过程可以大概由下面这张图来概括:

首先,插入的数据会进入一个内存中的 insert buffer。这些 buffer 会由开始的 Mutable 状态周期性的转为 Immutable 状态,以准备序列化。然后,这些 Immutable buffer 会周期性的被后台序列化线程序列化到磁盘。数据落盘后,落盘信息会被记录在元数据里。至此,数据就能被搜到了!

现在,我们会具体描述图中的步骤。

数据插入 Mutable buffer 的过程我们都已经知道了,接下来,就是从 Mutable buffer 转为 Immutable buffer 的过程:

Immutable queue 这个队列会向后台序列化线程提供 immutable 状态的,已经准备好被序列化的 MemTableFile。每个 MemTable 管理着自己的 immutable queue,当 MemTable 唯一 mutable 的 MemTableFile 大小达到阈值,就会进入 immutable queue。一个负责 ToImmutable 的后台线程会周期性的拉取所有 MemTable 管理的 immutable queue 中的 MemTableFile,并将他们输送到总的 Immutable queue。需要注意的是,数据写入内存和将内存中的数据变为不可被写的状态这两个操作不能同时发生,需要共用一把锁。但是,ToImmutable 这个操作因为过程很简单,几乎不会造成任何延迟,所以对插入数据的性能影响微乎其微。

接下来就是将 serialization queue 中的 MemTableFile 序列化到磁盘了。这主要分为三步:

首先,后台序列化线程会周期性的从 immutable queue 中拉取 MemTableFile。然后,他们被序列化成固定大小的原始文件(Raw TableFiles)。最后,我们会将这个信息记录在元数据中。当我们进行向量搜索时,我们会在元数据中查询对应的 TableFile。至此为止,这些数据就能被搜索到了!

此外,根据设置的 index_file_size,后台序列化线程在完成一次序列化周期后,会将一些固定大小的 TableFile 合并成一个 TableFile,并且同样在元数据中记录这些信息。这时候,这个 TableFile 就可以被构建索引了。构建索引同样也是异步的,另外一个负责构建索引的后台线程会周期性的读取元数据中 ToIndex 状态的 TableFile,进行对应的索引构建。

| 向量搜索

实际上,你会发现,通过 TableFile 和元数据的帮助,向量的搜索变得更加直观和方便。大体上说,我们需要从元数据中获取与被查询 Collection 对应的 TableFiles,在每个 TableFile 进行搜索,最后进行归并。在这篇文章里,我们不深入探讨搜索的具体实现。如果你想要了解更多,欢迎阅读我们的源码,或者阅读 Milvus 系列的其他文章!

本文分享自微信公众号 - ZILLIZ(Zilliztech),作者:竺知茹

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Chat with Milvus #24 回顾-Milvus 数据管理

    不管是分区还是段,都只是数据在物理存储中的组织形式。Milvus 进行查询操作时,必须要获知各个数据文件在物理存储上的位置以及状态信息,包括所属集合、包含的实体...

    ZILLIZ
  • 异构计算系列文章(一):定义、场景及局限性

    2020 开年,ZILLIZ 与 InfoQ 筹备了以异构计算为专题的一系列文章。此篇文章作为异构计算专题的开篇,整体性的介绍了异构计算的定义、场景与局限性。在...

    ZILLIZ
  • Milvus 数据段合并机制

    我们在《Milvus在大规模向量检索场景下的数据管理》这篇文章说过,当向量数据不断地进入 Milvus 时,系统后台会持续地将插入缓冲区中的数据写入磁盘,形成很...

    ZILLIZ
  • 大咖丨交通运输部科学研究院:交通运输大数据的基础环境正日益成熟-清数•思享会

    大数据文摘
  • 神策数据创始人兼CEO桑文锋:大数据分析的四个重要环节(内附视频&PPT)

    数据猿导读 在“硅谷之声——大数据技术达人中国行专场”上,神策数据创始人兼CEO桑文锋表示,在百度工作这么多年,“要把数据的事情做好”是我非常重要的一个心得。数...

    数据猿
  • 大数据到底如何在企业中发挥价值

    一、企业大数据如何起步:从小数据到大数据 目前国内外关于大数据的谈论很多,大多是谈运营级别的,或者说从服务端、服务方提得较多一些。笔者要跟大家交流的问题是作为各...

    用户1410343
  • 大麦网周宇红:用大数据打破票务行业的天花板

    “每天一个数据”分析师新一期内容奉上,请享用~ 采访 | Penny 整理 | Sophie 转载请注明来自CDA数据分析师 否则小编将举报到底! 人物档案 周...

    CDA数据分析师
  • 【CDAS 2017】大数据与云计算分论坛:云计算驱动下的大数据

    作者 CDA 数据分析师 前言 2017年7月29日,由CDA数据分析师主办,以“跨界互联 数据未来”为主题的CDAS 2017第四届中国数据分析师行业峰会...

    CDA数据分析师
  • 大数据相关的职业岗位及主要工作内容

    大数据正在改变全球商业运作方式,随着对合格大数据人才需求的增加,大数据行业的发展空间和待遇也越来越好,很多想转行大数据的入门学习者,不太清楚大数据的...

    加米谷大数据
  • Mysql删除表数据,表文件大小不变

    首先明确一个概念,innodb表包含两部分,表结构定义和数据,Mysql8.0以前表结构定义存放在.frm为后缀的文件里,而Mysql8.0版本以后允许表结构定...

    小土豆Yuki

扫码关注云+社区

领取腾讯云代金券