前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Milvus存算分离系列-2: target机制

Milvus存算分离系列-2: target机制

作者头像
MrPresent-Han
发布2023-09-17 12:29:38
3210
发布2023-09-17 12:29:38
举报
文章被收录于专栏:数据库开发优化

前言

无论是存算分离还是存算一体,client对于查询的正确性要求都是一致的,没有哪个客户会因为所谓的“架构优势”牺牲正确性,即使是ANN这样的‘近似查询’。而对于存算分离的架构,由于“存”和“算”发生的进程是不同的,那么如何保证数据的完整性&&一致性就是一个相比于存算一体更复杂的问题。本文从这个问题出发,介绍milvus是怎么在存算分离架构下保证查询数据的完整性,一致性和实时性的。本文涉及到一些前置知识,如果对读者造成困惑,可以参考MrPresent-Han:Milvus 存算分离系列-1:milvus架构简介

存算分离的难点:数据实时更新

在讨论数据完整性之前,我们首先要明确数据实时更新带来的困难。假如数据没有实时写入,只是批量导入,那么“一存多用”就可以简化为下载+复制的问题,从而保证极佳的扩展性和相当低的复杂度。但问题是,数据库不是数据湖,绝大多数用户都不能接受小时甚至分钟级别的数据可见延迟,有些用户甚至要求新写入的数据立即可见,这就给存算分离架构带来了额外的复杂性。

Milvus是怎么在存算分离架构下保证数据实时可见&&数据完整性的?

这个问题的答案有2点,第一是target机制,第二是存算双写。

Milvus target机制

如前文所言,在milvus中,segment相当于是一张表的水平切片,同时也是分布式的最小unit。而milvus的target,可以暂时简单理解为“可读segment的集合”。

targe机制简图
targe机制简图

如上图所示,随着时间线的推进,client不断插入数据,在storage侧生成新的segment,由于target是immutable的,所以新的target会生成。mixCoord会定期检查target状态,当发现存在新的target的时候,就会命令compute节点load新的segment以供client查询,从而保证新写入的数据能被client正确查询到。

target推进机制

如上图所示,似乎target机制的推进和更新是一件非常简单的事情, 只要compute节点把object storage上的新的segment文件download下来就可以了,但实际上并没有着么简单。主要的难点有2处:

  • compaction问题
  • 索引问题

本文先说compaction

基本上lsm的storage设计都得接受compaction引入的额外复杂性。由于生成的segment是immutable的,那么小文件的控制和delete apply这两个关键问题都要依赖compaction。而在考虑compaction的情况下,target机制就没有上图展示的那么简单了。

如上图所示,在target3-target4的这个时间段内,segment1和segment2被compact成了segment4,而且数据写入又新生成了segment5。此时,对于client来说,有效的target=[segment3, segment4, segment5], 不应该包括segment1和2,否则会有结果数据重复的错误和重复计算的资源浪费,因此需要对segment1和segment2进行卸载并对segment5进行加载,从而完成整个target更新。

target中间状态处理

在复杂系统的设计过程中,一个很头疼点的点就是状态转换设计,只有系统的状态转换正确,一致性&&可用性才能有保证。而在状态转换过程中,Todo和Done状态往往是比较可控的,但是在两者之间的Doing状态,却是系统最容易出错甚至挂掉的点。那么就Milvus Target机制而言,比较典型的中间状态如下图。

新上旧未下
新上旧未下

首先是‘新上旧未下’的情况,即在某个时间点,新生成segment4已经加载了,但是segment2还没卸载,此时client会看到segment2上冗余的数据。

旧下新未上
旧下新未上

然后就是相反的情况,旧segment1和2都已经卸载了,但是新的segment4还没加载,此时client查询会发现少数据。

以上这两种情况,其实都是“Doing”问题,解决这种Doing问题可以采用2个点,第一是顺序,第二是commitPoint。那么在milvus的target机制中,我们如下设计。

  1. 定义顺序:所有target中的segment必须“先上后下”,即新的segment必须加载完成,对应的旧segment才能卸载
  2. 定义commitPoint: 必须所有新的segment都加载完成,target更新才算完成,client所使用的target才能推进,否则

Segment冗余问题处理:targetVersion

部分读者可能已经发现上文的一个漏洞,到达commitPoint的时候,旧的segment还没有卸载掉,所以segment事冗余的,那么如何避免client读到旧的segment呢?答案是在target和segment之间建立targetVersion关系。

target3推进到target4
target3推进到target4

如上图所示,当mixCoord发现已经到达commitPoint的时候,会将仍然在target4包含的segment3-4-5对应的targetVersion更新为t4, 而segment1-2因为已经不在target中了,所以其对应的targetVersion没有更新,仍然是target3。当client查询发生的时候,当前可用的targetVersion是t4,所以query会忽略segment1和segment2,从而避免查询到冗余的segment。

注意,为了方便理解,部分细节被简化省略掉了。比如熟悉Milvus源码的同行可能知道,target的推进并不是mi xCoord直接指示querynode完成的,而是通过delegator进行的。这种细节并不影响整体理解,所以本文及后续系列文章会选择性地省略掉类似细节。

总结

本文主要介绍了Milvus在存算分离架构下的target推进机制,在实际系统构件和运维过程中,还有很多其他的中间状态和细节问题需要解决,例如多副本,负载均衡,资源隔离。这些细节问题我们会在后续文章中一一补充。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 存算分离的难点:数据实时更新
    • Milvus是怎么在存算分离架构下保证数据实时可见&&数据完整性的?
    • Milvus target机制
      • target推进机制
        • target中间状态处理
          • Segment冗余问题处理:targetVersion
            • 总结
            相关产品与服务
            向量数据库
            腾讯云向量数据库(Tencent Cloud VectorDB)是一款全托管的自研企业级分布式数据库服务,专用于存储、检索、分析多维向量数据。该数据库支持多种索引类型和相似度计算方法,单索引支持千亿级向量规模,可支持百万级 QPS 及毫秒级查询延迟。腾讯云向量数据库不仅能为大模型提供外部知识库,提高大模型回答的准确性,还可广泛应用于推荐系统、自然语言处理等 AI 领域。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档