1、Milvus简介
1.1、什么是 Milvus
Milvus 是一款云原生向量数据库,它具备高可用、高性能、易拓展的特点,用于海量向量数据的实时召回。
Milvus 基于 FAISS、Annoy、HNSW 等向量搜索库构建,核心是解决稠密向量相似度检索的问题。在向量检索库的基础上,Milvus 支持数据分区分片、数据持久化、增量数据摄取、标量向量混合查询、time travel 等功能,同时大幅优化了向量检索的性能,可满足任何向量检索场景的应用需求。通常,建议用户使用 Kubernetes 部署 Milvus,以获得最佳可用性和弹性。
Milvus 采用共享存储架构,存储计算完全分离,计算节点支持横向扩展。从架构上来看,Milvus 遵循数据流和控制流分离,整体分为了四个层次,分别为接入层(access layer)、协调服务(coordinator service)、执行节点(worker node)和存储层(storage)。各个层次相互独立,独立扩展和容灾。
1.2、为什么需要 Milvus
随着互联网不断发展,电子邮件、论文、物联网传感数据、社交媒体照片、蛋白质分子结构等非结构化数据已经变得越来越普遍。如果想要使用计算机来处理这些数据,需要使用 embedding 技术将这些数据转化为向量。随后,Milvus 会存储这些向量,并为其建立索引。Milvus 能够根据两个向量之间的距离来分析他们的相关性。如果两个向量十分相似,这说明向量所代表的源数据也十分相似。
Milvus 向量数据库专为向量查询与检索设计,能够为万亿级向量数据建立索引。
与现有的主要用作处理结构化数据的关系型数据库不同,Milvus 在底层设计上就是为了处理由各种非结构化数据转换而来的 Embedding 向量而生。
1.3、为什么选择使用 Milvus
- 高性能:性能高超,可对海量数据集进行向量相似度检索。
- 高可用、高可靠:Milvus 支持在云上扩展,其容灾能力能够保证服务高可用。
- 混合查询:Milvus 支持在向量相似度检索过程中进行标量字段过滤,实现混合查询。
- 开发者友好:支持多语言、多工具的 Milvus 生态系统。
2、Milvus 基本概念
- 非结构化数据
- 非结构化数据指的是数据结构不规则,没有统一的预定义数据模型,不方便用数据库二维逻辑表来表现的数据。
- 非结构化数据包括图片、视频、音频、自然语言等,占所有数据总量的 80%。
- 非结构化数据的处理可以通过各种人工智能(AI)或机器学习(ML)模型转化为向量数据后进行处理。
- 特征向量
- 向量又称为 embedding vector,是指由 embedding 技术从离散变量(如图片、视频、音频、自然语言等各种非结构化数据)转变而来的连续向量。
- 在数学表示上,向量是一个由浮点数或者二值型数据组成的 n 维数组。
- 通过现代的向量转化技术,比如各种人工智能(AI)或者机器学习(ML)模型,可以将非结构化数据抽象为 n 维特征向量空间的向量。这样就可以采用最近邻算法(ANN)计算非结构化数据之间的相似度。
向量相似度检索
- 相似度检索是指将目标对象与数据库中数据进行比对,并召回最相似的结果。同理,向量相似度检索返回的是最相似的向量数据。
- 近似最近邻搜索(ANN)算法能够计算向量之间的距离,从而提升向量相似度检索的速度。如果两条向量十分相似,这就意味着他们所代表的源数据也十分相似。
Collection
- 包含一组 entity,可以等价于关系型数据库系统(RDBMS)中的表。
Entity
- 包含一组 field。field 与实际对象相对应。field 可以是代表对象属性的结构化数据,也可以是代表对象特征的向量。primary key 是用于指代一个 entity 的唯一值。
- **注意:** 你可以自定义 primary key,否则 Milvus 将会自动生成 primary key。请注意,目前 Milvus 不支持 primary key 去重,因此有可能在一个 collection 内出现 primary key 相同的 entity。
Field
- Entity 的组成部分。Field 可以是结构化数据,例如数字和字符串,也可以是向量。
**注意:**
Milvus 2.0 现已支持标量字段过滤。并且,Milvus 2.0 在一个集合中只支持一个主键字段。
Milvus 与关系型数据库的对应关系如下:
Milvus 向量数据库 | 关系型数据库 |
Collection | 表 |
Entity | 行 |
Field | 表字段 |
Partition
- 分区是集合(Collection)的一个分区。Milvus 支持将收集数据划分为物理存储上的多个部分。这个过程称为分区,每个分区可以包含多个段。
Segment
- Milvus 在数据插入时,通过合并数据自动创建的数据文件。一个 collection 可以包含多个 segment。一个 segment 可以包含多个 entity。在搜索中,Milvus 会搜索每个 segment,并返回合并后的结果。
Sharding
- Shard 是指将数据写入操作分散到不同节点上,使 Milvus 能充分利用集群的并行计算能力进行写入。默认情况下,单个 Collection 包含 2 个分片(Shard)。目前 Milvus 采用基于主键哈希的分片方式,未来将支持随机分片、自定义分片等更加灵活的分片方式。
**注意:** 分区的意义在于通过划定分区减少数据读取,而分片的意义在于多台机器上并行写入操作。
索引
- 索引基于原始数据构建,可以提高对 collection 数据搜索的速度。Milvus 支持多种索引类型。为提高查询性能,你可以为每个向量字段指定一种索引类型。目前,一个向量字段仅支持一种索引类型。切换索引类型时,Milvus 自动删除之前的索引。
相似性搜索引擎的工作原理是将输入的对象与数据库中的对象进行比较,找出与输入最相似的对象。索引是有效组织数据的过程,极大地加速了对大型数据集的查询,在相似性搜索的实现中起着重要作用。对一个大规模向量数据集创建索引后,查询可以被路由到最有可能包含与输入查询相似的向量的集群或数据子集。在实践中,这意味着要牺牲一定程度的准确性来加快对真正的大规模向量数据集的查询。
PChannel
- PChannel 表示物理信道。每个 PChannel 对应一个日志存储主题。默认情况下,将分配一组 256 个 PChannels 来存储记录 Milvus 集群启动时数据插入、删除和更新的日志。
VChannel
- VChannel 表示逻辑通道。每个集合将分配一组 VChannels,用于记录数据的插入、删除和更新。VChannels 在逻辑上是分开的,但在物理上共享资源。
3、Milvus 版本特性
1、Milvus 3.x
- 架构升级
- GPU 支持 (2.x 版本不支持)
- QueryNode核心服务重写(稳定性提升)
- IndexCoord 和 Datacoord 合并(降低了元信息在不同 coord 之间通信的成本)
- 新增功能
- Upsert 功能
- 支持用户通过 upsert 接口更新或插入数据。已知限制,自增 id 不支持 upsert;upsert 是内部实现是 delete + insert 所以性能上会有一定损耗,如果明确知道是写入数据的场景请继续使用 insert
- Range Search 功能
- 持用户通过输入参数指定 search 的 distance 进行查询,返回所有与目标向量距离位于某一范围之内的结果
- RangeSearch 依然具有最大返回结果不超过 16384 条的限制
- Count 接口
- 提供了 count(*) 表达式,可以实时计算准确的 collection 行数
- count 操作较为消耗资源,不建议大量并发调用
- Cosine metrics
- 原生支持了 Cosine 距离,用户不再需要通过向量归一化计算 IP metrics 来使用 cosine 距离
- 查询返回原始向量
- 出于查询性能的考虑,之前的版本中 Milvus 不支持返回原始向量,此版本中补齐了该功
- 返回原始向量会有二次查询产生,所以对性能会产生较大影响,如果是性能 critical 场景,建议使用 HNSW、IVFFLAT 等包含原始向量的索引
- ScaNN 索引
- Milvus 目前支持了 Faiss 中的 FastScan 算法,在各项 benchmark 中有着不俗的表现,对比 HNSW 有 20% 左右提升,约为 IVFFlat 的 7 倍,同时构建索引速度更快
- Iterator
- Pymilvus 中提供了 iterator 接口,可以通过迭代器的方式拉取数据,Query 和 Range Search 场景下,通过迭代器可以获取超过 16384 条数据限制的数据。Iterator 类似于 ES 的 scroll 接口和关系数据库中的 cursor,比较适合后台批量处理数据。
- CDC 支持
- Change Data Capture 是数据库系统中很通用的功能,可以用于跨机房主备数据同步、增量数据备份、数据迁移等场景,Milvus 的 CDC 代码在 https://github.com/zilliztech/milvus-cdc
- Upsert 功能
- Enhancement
- MMap 技术提升数据容量
- MMap 是 Linux 内核提供的技术,可以将一块磁盘空间映射到内存,这样一来我们便可以通过将数据加载到本地磁盘再将磁盘 mmap 到内存的方案提升单机数据的容量,经过测试使用 MMap 技术后数据容量提升了 1 倍而性能下降在 20% 以内,大大节约了整体成本,对于成本敏感的用户欢迎试用此功能。
- filter 场景性能提升
- 对于标量向量的混合查询场景,Milvus 的执行计划是先执行标量过滤再执行向量检索,这就意味着标量过滤之后会有大量的数据被过滤掉,如果过滤掉的数据过多会引起向量索引性能急剧下降,通过优化 HNSW 索引的数据过滤策略,2.3.0 中优化了此场景中的性能。除此之外,通过引入手动的向量化执行技术,标量数据过滤的速度也得到了大幅提升。
- Growing 索引
- Milvus 的数据分为两类,分别为已索引的数据和流式数据。对于已索引的数据自然可以使用索引加速查询,但流式数据只能使用逐行暴力检索,对性能影响较大,为了解决此类问题在 2.3.0 中加入了 Growing index,自动为流式数据建立实时索引,保障查询性能。
- 多核环境资源利用率提升
- 向量近似计算是计算密集型的任务,CPU 使用率是非常重要的指标,在 CPU 核数较多的情况下可能会出现 CPU 使用率无法超过 70% 的情况,经过优化 Milvus 2.3.0 能够更加充分利用好 CPU 资源实现性能提升。
- MMap 技术提升数据容量
- 稳定性提升
- New load balance
- 在 2.1.0 版本中,Milvus 支持了内存多副本,用户可以通过多副本的方式提升 QPS。经过半年多的生产实践,收到了很多来自社区的反馈,其中主要集中在添加副本后 QPS 没有立刻提升、节点下线后系统恢复稳定时间较长、节点之间负载不均衡、CPU 使用率不高等问题。这些问题归因到一起可以认为是负载均衡逻辑鲁棒性低,故障恢复能力较弱的问题,经过重新设计的负载均衡算法,采用基于负载的动态负载均衡算法,能够及时的发现节点上下线、负载不均衡等现象及时调整请求调度。经过测试可以在秒级发现故障、负载不均衡、节点上线等事件,及时调整负载。
- 动态配置
- 修改配置是运维、调优数据库中的常见操作,从此版本开始 Milvus 支持动态修改配置项而无需重启集群,支持的方式有两种一是修改 etcd 中的 kv,二是直接修改 Milvus.yaml 配置文件。需要注意的是并不是所有的配置项都支持动态配置
- New load balance
- Tracing 支持
- 通过 tracing 发现系统中的瓶颈点,是调优的重要手段,从 2.3.0 开始 Milvus 支持 Opentelemetery tracing 协议,支持此协议的 tracing collector 例如 jaeger 都可以接入观测 Milvus 的调用路径。
- Error Code 增强
- 团队重新梳理了 Milvus 的 error code 以及设计了新版 error code 的架构,这次升级后,Milvus 的报错会更清晰。
- Birdwatcher tool 升级
-
- 支持 restful API,更方便集成到其他诊断系统中
- 支持 pprof 命令,更方便的与 go pprof tool 集成
- 增加 storage analysis 命令分析存储占用
- 与 2.3.0 的 event log 模式集成,支持通过结构化的数据分析 Milvus 内部事件,提升分析日志效率
- 支持修改 / 查看 etcd 中的配置
- Break Change
- 移出 Time travel 功能
- 由于 Time travel 功能几乎没有用户使用,且 time travel 功能对 Milvus 的系统设计提出了较大挑战,先暂时废弃。‘
- 移出 CentOS7 支持
- 由于 centos 官方对 centos7 的支持即将到期,而且 centos8、centos9 仅有 stream 版本,官方并未提供正式的 docker 镜像,所以 Milvus 放弃对 centos 的支持,改为使用 Amazonlinux 发行版进行替代。此外,基于 ubuntu20.04 的镜像依旧是 Milvus 的主推版本。
- 删除了部分索引和 Metrics 支持
- 删除了包括 Annoy 索引和 RHNSW 索引,以及 binary 向量下的 Taninato、Superstructure 和 substructure 距离。
4、Milvus 系统架构
Milvus 2.0 是一款云原生向量数据库,采用存储与计算分离的架构设计,所有组件均为无状态组件,极大地增强了系统弹性和灵活性。
整个系统分为四个层次:
各个层次相互独立,独立扩展和容灾。
3.1、接入层
接入层由一组无状态 proxy 组成,是整个系统的门面,对外提供用户连接的 endpoint。接入层负责验证客户端请求并减少返回结果。
3.2、协调服务
协调服务是系统的大脑,负责向执行节点分配任务。它承担的任务包括集群拓扑节点管理、负载均衡、时间戳生成、数据声明和数据管理等。
协调服务共有四种角色:
3.3、执行节点
执行节点是系统的四肢,负责完成协调服务下发的指令和 proxy 发起的数据操作语言(DML)命令。
由于采取了存储计算分离,执行节点是无状态的,可以配合 Kubernetes 快速实现扩缩容和故障恢复。
执行节点分为三种角色:
3.4、存储服务
存储服务是系统的骨骼,负责 Milvus 数据的持久化,分为元数据存储(meta store)、消息存储(log broker)和对象存储(object storage)三个部分。
元数据存储
负责存储元信息的快照,比如:集合 schema 信息、节点状态信息、消息消费的 checkpoint 等。元信息存储需要极高的可用性、强一致和事务支持,因此,etcd 是这个场景下的不二选择。除此之外,etcd 还承担了服务注册和健康检查的职责。
对象存储
负责存储日志的快照文件、标量 / 向量索引文件以及查询的中间处理结果。Milvus 采用 MinIO 作为对象存储,另外也支持部署于 AWS S3 和 Azure Blob 这两大最广泛使用的低成本存储。但是,由于对象存储访问延迟较高,且需要按照查询计费,因此 Milvus 未来计划支持基于内存或 SSD 的缓存池,通过冷热分离的方式提升性能以降低成本。
消息存储
消息存储是一套支持回放的发布订阅系统,用于持久化流式写入的数据,以及可靠的异步执行查询、事件通知和结果返回。执行节点宕机恢复时,通过回放消息存储保证增量数据的完整性。
目前,分布式版 Milvus 依赖 Pulsar 作为消息存储,单机版 Milvus 依赖 RocksDB 作为消息存储。消息存储也可以替换为 Kafka、Pravega 等流式存储。
整个 Milvus 围绕日志为核心来设计,遵循日志即数据的准则,因此在 2.0 版本中没有维护物理上的表,而是通过日志持久化和日志快照来保证数据的可靠性。
日志系统作为系统的主干,承担了数据持久化和解耦的作用。通过日志的发布订阅机制,Milvus 将系统的读、写组件解耦。一个极致简化的模型如上图所示,整个系统主要由两个角色构成,分别是消息存储(log broker)(负责维护”日志序列 “)与“日志订阅者”。其中的“日志序列” 记录了所有改变库表状态的操作,“日志订阅者”通过订阅日志序列更新本地数据,以只读副本的方式提供服务。 发布订阅机制还为系统在变更数据捕获(CDC)和全面的分布式部署方面的可扩展性提供了空间。
4、Milvus 主要的组件
Milvus 支持两种部署模式,单机模式(standalone)和分布式模式(cluster)。两种模式具备完全相同的能力,用户可以根据数据规模、访问量等因素选择适合自己的模式。Standalone 模式部署的 Milvus 暂时不支持在线升级为 cluster 模式。
4.1、单机版 Milvus
单机版 Milvus 包括三个组件:
4.2、分布式版 Milvus
分布式版 Milvus 由八个微服务组件和三个第三方依赖组成,每个微服务组件可使用 Kubernetes 独立部署。
微服务组件
第三方依赖
5、Milvus 应用场景
你可以使用 Milvus 搭建符合自己场景需求的向量相似度检索系统。Milvus 的使用场景如下所示:
6、参考文章:
1、https://blog.csdn.net/sinat_39620217/article/details/131688885
- 本文固定链接: http://www.jiagou.cc/240/
- 转载请注明: 摘星怪 于 架构迷 发表