随着 Milvus 的持续迭代,越来越多的用户将其作为构建生产环境的向量数据服务。作为数据服务运维,数据安全、容灾备份自然是用户最关心且不容有失的需求。为解决这一刚需,Milvus-backup 项目应运而生。
Milvus-backup[1] 是 Zilliz 专门为 Milvus 开发的数据备份和恢复工具。不同于之前推出的 Milvus 图像化管理工具 Attu[2] 和 ANN 算法可视化工具 Feder,这次我们没有起一个特别的名字,而是直截了当地表明功能。
读完本文,用户可以快速掌握 Milvus-backup 的功能特点和使用方法。
Milvus-backup 支持以下能力:
Milvus-backup 使用 go 语言实现,部分逻辑直接拷贝 Milvus 源码,保证最大程度的兼容性和操作习惯一致性。
Milvus-backup 支持多种使用方式:
1. 命令行
考虑备份工具的主要用户是对 Milvus 的运维开发人员,命令行是最简便直接的使用方式,Milvus-backup 基于 cobra 框架实现了命令行。
2. Restful API
Milvus-backup 还提供 Restful API,便于工具服务化,并提供 Swagger UI。
3. Go module
Milvus-backup 还可以作为 go module,集成到其他工具之中。例如,未来我们会提供 all in one 的 Milvus 工具箱,将包括 Milvus-backup 在内的运维工具一起打包。
熟悉 Milvus 系统的朋友知道,Milvus 目前使用 etcd 存储元数据(以下称为 metadata),使用对象存储(minio、S3 等)存储真实数据(以下称为 storage)。未来,Milvus 可能会支持更多的存储介质,如 MySQL、Alluxio、HDFS 等,在设计上要考虑兼容性。
因此我们采用的方案是:
Metadata 不直接调用 etcd 接口,而是通过 Milvus SDK 获取必要信息,存储到自定义的 backup metadata 文件中,backup metadata 使用 json 格式,便于观察和适配;
storage 通过调用存储 SDK 直接复制数据到指定路径,备份数据和原数据几乎保持相同路径结构,降低理解成本。
在备份的时候,工具会调用 Milvus 的 flush 接口来获得备份的快照时间戳,这是备份环节唯一会影响 Milvus 集群的地方,但影响很小。
不直接操作 metadata 和 storage,而是调用 Milvus SDK 重新创建 collection,通过 2.2.0 新推出的 bulkinsert 功能,将数据批量插入到新建 collection 中,因此逻辑上备份恢复得到的是一张新表,只不过与原表数据内容一致。
Milvus-backup 主要包含以下接口,分别是备份(backup)和恢复(restore)的主要操作:
详情可参考 backup.go[4]。
下面使用项目中的例子来讲解 Milvus-backup 的使用方法。示例可在 README 中找到。
1. 集群和数据准备 Prepare
测试备份恢复首先需要有一个可用的 Milvus 集群,启动集群参考官方文档[5]。
集群启动完成后,创建一些测试数据,可以使用项目中的示例代码:
python example/prepare_data.py
这将会创建两个 collection:hello_milvus 和 hello_milvus2,并分别向其中插入了 3000 和 6000 条数据。
2. 编译和配置 Build & Config
目前,工具使用需要自行下载代码编译:
go get
go build
编译完成会在当前路径下产生可执行文件milvus-backup
。
Milvus 需要连接执行备份/恢复的集群以及其使用的 minio,相关的配置见 configs/backup.yaml 文件。配置项和 Milvus 极为相似。
Milvus-backup 配置文件
配置完成后执行./milvus-backup --help
来观察下说明。几个子命令分别对应着几个核心接口。
Milvus-backup 命令行说明
需要说明的是,server 子命令可以启动 Restful API 服务。
Milvus-backup server 子命令说明
例如执行.milvus-backup server run -p 8090
,访问 localhost:8090/api/v1/docs/index.html。
结果如下:
Milvus-backup RestAPI Swagger UI
如果展示 RestAPI 的 Swagger UI,说明配置成功。
3. 备份 Backup
执行如下的备份命令:
./milvus-backup create -n my_backup
这会将当前集群中所有的 collection 备份下来,my_backup
是备份的名字,每个备份必须有一个名字,且不能重名。
执行完,我们可以通过 minio 的 UI[6] 来看一下备份的样子。
可以看到在 a-bucket/backup(和配置一致)路径下以备份的名字创建了路径 my_backup,下面有两个文件夹分别存储着备份的元数据(meta)和真实数据(binlog)。
minio 中 backup 存储示例
meta 下是四个的元数据文件,分别记录着 backup、collection、partition、segment 四个层级的元数据。感兴趣的用户可以下载下来浏览,字段基本可以实现顾名思义。binlogs 路径下是和 Milvus 存储几乎一样的层次结构。
backup meta 存储示例
随后,还可以分别使用 get 和 list 命令查看一下这个备份:
./milvus-backup list
./milvus-backup get -n my_backup
4. 恢复 Restore
有了备份之后就可以执行恢复,在这里我们只测试在同一集群进行备份恢复,如果需要从集群 A 备份恢复到集群 B,需要更改配置文件,修改连接的 Milvus 和 minio 配置即可。
Milvus-backup restore 子命令说明
鉴于恢复可能会出现 collection 名冲突的情况,我们提供灵活的处理方式:
-s或--suffix
参数设置统一后缀,即 hello_milvus 会恢复成 hello_milvus_recover。-r或--rename
参数设置传一组 kv,指定对每一个表进行重命名。此处执行:
./milvus-backup restore -n my_backup -s _recover
需要强调的是恢复使用了 Milvus 2.2.0 发布的 bulkinsert 功能,恢复花费时间和数据量正相关。
5. 校验 Verify
按照上面的操作到这里,我们预期已经在集群内恢复出了两个 collection:hello_milvus_recover 和 hello_milvus2_recover。它们理应可以正常工作并且和原表数据一致。
因而可以执行校验脚本,在新 collection 上查看行数、创建索引、执行搜索。正常情况下可以顺利执行。
python example/prepare_data.py
校验脚本输出示例
至此便完成了一次备份到恢复的全过程,具体更多的使用细节,可以使用--help
来查看各级命令的说明,也可以参考 Swagger UI 的接口说明和源代码。
未来我们会基于开源社区和 Zilliz Cloud 产品的需求逐步迭代备份恢复工具,目前包括:
1. 并发和限流控制
使用并发来提高备份和恢复的速度,支持限流控制来保证并发情况下的稳定性。
2. 各平台安装包
目前我们还没有发布各个平台的可执行文件安装包,将会在未来提供。
3. 增量备份
目前的备份只支持备份全量数据,未来我们会支持增量,提供更灵活的运维选择。
4. 索引备份
在一期项目中我们没有备份索引数据,因为相较于原数据,索引数据处于次一优先级;但索引创建是比较昂贵的操作,我们会考虑支持索引备份。
5. 冷备份
目前备份工具只支持热备份,即在 Milvus 工作的情况下执行备份,未来我们会考虑支持冷备份,即在集群停机/挂掉的情况下备份/抢救数据。
好的产品离不开用户的反馈,欢迎大家使用和提供建议!
[1]
Milvus-backup: https://github.com/zilliztech/milvus-backup
[2]
Attu: https://milvus.io/docs/attu.md
[3]
bulkinsert: https://milvus.io/docs/bulk_insert.md
[4]
backup.go:https://github.com/zilliztech/milvus-backup/blob/master/core/backup.go
[5]
官方文档: https://milvus.io/docs
[6]
UI: http://localhost:9001/