https://v.qq.com/x/page/r31000kfvjc.html
| Milvus Q&A 部分文字实录
Attendee= 参会者
Attendee A:你好顾老师, 我想了解一下 Mishards 它具体在扩容的过程怎么实现的?动态扩容那一步,就是 Milvus readonly 服务它扩容具体怎么实现?
顾老师 @Milvus: 现在我们的分布式其实是做第一步相对比较简单的,应该称之为分布式扩展。我们还没有把整个 Milvus 构建成一个分布式集群的模式,因为之前也跟大家有解释这个原因,其实我们有很多功能还在不断的引入当中。因为一个分布式集群,当你开始做分布式集群的时候,就意味着你自己自身的单点的能力也好,都要相对到一个平台期,那么在做那个会比较的自然一点,不然的话因为我们现在很多功能要引入进去,那么其实如果是在一个分布式集群的环境里面的话,它会变得非常的复杂,所以现在更多的是做一个分布式扩展。
分布式扩展其实是现在主要的方式,也就是提供一些这种分布式代理像 Mishards,然后前面可以借 nginx 去帮助大家做一些这种动态的负载均衡。扩容这部分的话,其实我们即便是把它做成一个集群,我们因为最终奔着一个云的环境去的,所以我们也不会说把所有的功能都让自己去做实现,更多的是会利用现代的组件,怎么样去利用 k8s 去新增节点,然后去注册服务,然后怎么样把它加入到负载均衡的里面,所以其实我们不会说自己单纯做一套完整的东西去做所有的东西。
Attendee A:在查询文件的过程中是挨个对文件进行查找,然后查找过来,然后在内存中....
顾老师 @Milvus:你是说搜索的时候?
Attendee A:对,我在看的查找的过程中,不是挨个文件,就是在 search 的时候挨对每一个文件夹进行比较,求出 Top N,然后再归并是吧?
顾老师 @Milvus:对的,是这么个过程。
Attendee A:我看到咱的在知乎上分享的文章里面,怎么是还往内存中加载的时候用的 LRU(Least Recently Used)策略,既然对每一个文件都进行了 Top N,它不就没有必要进行 LRU?
顾老师 @Milvus:这个是两个不同的方面,LRU 主要是指的是因为在 Milvus 服务当中,它有一个内存当中的 cache 缓存这一层,那么其实所有的数据文件都先放在内存当中,然后我去进行搜索,这是速度最快的。所以这部分是挨个搜索其实就是发生在内存里的。但是如果说你的文件特别大,然后你的服务器内存也不是那么够,那么你不可能把所有的文件都放在内存里面,这个缓冲区它肯定需要一些淘汰的机制,对吧?
我读了 10 个文件,现在你第 11 个文件要进来,我不是已经放不下了,我就要把最早的文件清除掉,释放的空间去给后面新的文件。它其实更多是指的一个缓冲区的内存淘汰的一个机制。您那边现在是一个什么样的场景?
Attendee A:就是 10 亿级的这种的向量,512 维的。如果我一个节点写入,然后多个节点可以查询的话,我从删除然后到可以进行查询,可以同步到这能用,这多长时间?
顾老师 @Milvus:你是说被删掉的,然后到查询的时间是吗?肯定是要有一个延迟的。你如果要在 10 亿的规模上做一个几百的并发度的话,其实已经算是一个比较高的规模相对会比较大一点,硬件的规模。
Attendee A:实际上咱们那个工具的话算了一下,1700多G。
顾老师 @Milvus:10 亿的话内存的话,我想一想,如果你是带压缩的话,应该不会那么大,可能在 500 就 600 多 G 左右。如果不这样做的话,可能它就一个 T,一点几个 T 了。
Attendee A:对。就这种全量匹配的不进行压缩的话,也不进行聚类,如果这样查询的话,这种速度查 Top10 的话,多长时间能够返回?
顾老师 @Milvus:10 亿的我们没有测过 512 的,我们只测过 128 的,128 的 10 亿的带点压缩的话,差不多是在 400 毫秒左右。因为我们公开数据是 128 维的 sift-1b 的数据集。
Attendee A:咱们提供的 bootcamp 里面,如果按分布式的操作的话,它只有没有 k8s的部署是吧?
顾老师 @Milvus:Bootcamp 里面我们应该没有给分布式的教程,应该分布式的教程都是在本身就是 Milvus 主 repo 的。因为 Bootcamp 中的教程都是偏向于一些小型的应用场景,就是告诉大家怎么和自己的应用去结合的。
Attendee A:Bootcamp 里面有一个叫《基于 Mishards 的分布式方案》,这个不是基于 k8s 的,它是直接自己部署的是吧?
顾老师 @Milvus:对的。所以你的并发度要能达到几百的话,你这个场景还是比较繁忙的,而且又不断的有数据更新进来。我不知道你这些更新的频率大概是什么样的?
Attendee A:整个底库的更新的话不是很大,但是有删除的操作。
顾老师 @Milvus:就是时不时有一些删除,但是更新的量每天会新增加来多少呢?百万级的吗?还是说千万级的这样?
Attendee A:每天大概百万级左右。
顾老师 @Milvus:其实之前也有很多人有类似的一个问题,我觉得给大家建议。把底库和增量的部分创建两个不同的索引的 collection,因为这样的话,不同的 collection 可以有不同的这种文件大小的配置,比较适合不同的场景。
因为底库本身特别大,但是又不怎么更新,相对来说比例不是那么高的话,它文件可以放大一点,它搜索的效率就会高一点。但是动态增加的部分就文件可以小一点的,你可以更快的构建起索引去搜索它。
B 同学是做电商的, 希望用 Milvus 做商品图片的搜索(因为多是做场景的讨论所以这里就不写出来, 想了解的可以看视频 16:27-38:30 的部分)
Attendee C:因为最近主要看向量搜索,其实我们主要是做 1 比 N 这个方案,让我看到了Milvus。然后我们之前考虑了有大概 4 个方案,1 个是 PG 的就是 PG 拿它插件,还有 image signal 来做,只不过它那个维度比较低。然后也考虑了一下 ES 的,只不过 ES 用了它特性 dense vector 来做,还也就前几天我看到你这个叫 Milvus 的。稍微测试了一下,感觉性能还有一些周边的生态都做得还可以,基础的有的都有,所以我想更深入的了解一下这块。
我现在的话我有几个问题,第一个像提取特征值这一块,因为刚才顾老师有说到 VGG 那个模型是吧?然后我想你们这边之后做就是说无论是图片还是一些文字,还是一些声音频之类的,像这种提取特征值这块你们有做一个什么口子来做吗?给别人提供一个比如说一个算法插件什么之类的,然后相当于直接把图片转成一些特征值,然后直接就可以跟你 Milvus 结合起来,会有这方面的考虑?
顾老师 @Milvus:是会有的,其实我们在做的图片搜索套件也是就帮助大家去构建这样一个 pipeline,然后你这边图片就是你配好流水线,然后你把图片提交过来之后,它可以帮你去按照你的要求的操作,比如说做一些对象的侦测,然后根据得出来的对象,然后去按照你指定的模型过一下这些特征值,然后再插入到 Milvus 当中。
但是因为这部分的东西它其实它更偏向于应用层,所以它不在 Milvus 里面,但是它会在非结构数据服务的大的框架里面,所以我们是会在 Milvus 的上游去提供这些东西,方便大家去做这些东西。
Attendee C:对这边可能更专注于做向量搜索引擎这一块整个的方案是吧?
顾老师 @Milvus:对,Milvus 本身它是一个怎么说,这是一个大的非结构数据服务当中一个比较核心的高性能的向量搜索引擎。然后什么模型的推理,pipeline 的构建,这些其实也在我这个框架里面,但是它是在 Milvus 的外部去做这些事情。
Attendee C:
我想问一下有没有一些落地的这种与业务场景的集成?就是与场景它肯定有一些业务场景方面的一些参数,这边的集成是怎么做的,因为我看到像比如说有图片,这可能用户说我根据以图所图,我可能在 Milvus 里面我可能搜出的是一段特征值,对吧?但是我最终要返回给用户的肯定不能是一些特征值,而且是相应的一些图片的数据。我现在想的看是不是大家都是用那个特征值的 ID 来做是吧?ID 来做一些相关的联系是吗?
顾老师 @Milvus:对没错,而且我们的以图搜图的示例里面也是这么搞的。
Attendee C:还有一个是涉及到分布式这一块,因为我们这边的量还是挺大的,量还是非常大。单依靠单机的话可能...单机的话不是说性能不好单机的话也好,但是可能还是想做分布式这一块。我看到这边只支持一个 Mishards 是吧?他好像是用 Python 来做的是吧?
顾老师 @Milvus:是的,但是后续其实这部分也会去做一些优化,然后我们肯定会提高扩展的能力,这是肯定的,只是说 Milvus 本身还有很多功能需要去增加进来,去帮助大家更好的处理非结构数据的,所以我们是把它单独当成一个新的场景,非结构数据服务的场景来做的。所以他其实会比一般的 ES 也好,或者说某一个结构化数据库的向量插件也好,它会有更多的东西和更多的可能性你要加入进去。所以在这部分确实我们是先想把基础打好了之后,再往这种集群的,分布式集群的方向去做一个延伸。
Attendee C:好的。我看了你们的一些文档,好像跟我理解的有些出入,我看你们这边是对请求,比如说他不同的用户,他可能发的有比如说 10 个关于特征检索的这一个请求,当然这个特征检索可能会分为不同的 collection。那么你这里我看到你们那边设计是将不同的请求分发到通过负载均衡一些方式,分发到不同的读写可读的节点去做的是吗?
顾老师 @Milvus:对,因为每个节点他有的服务的索引不可能是不一样的,比如说你有 10 个索引,10 个索引文件,可能 12345 在 A 节点的时候,678910 是在 B 节点上。因为你分布式扩展有几种,这有两种典型的情况,比如说第一种是你的 10 个索引文件,其实它太大,它超过了你单机内存能够处理的,能够容纳的一个大小,这个时候你做分布式的扩展,更多的是你扩机器来增加整个内存的容量,然后能够把所有这些文件放下,就可能是在节点 A 上有一些文件,在节点 B 上有一些文件。
它可能就是要去不同的机器去进行搜索,所以就会有一个路由的过程。情况就是说我可能就是只有一个数据文件,但是我一个机器可能跑不过来,我需要把它放在多个机器当中,我利用这个更多机器的 CPU 的计算的资源,来提供更高并发服务这样的一种模式,所以他其实会不太一样。
Attendee C:我看你们知乎上面有一篇专栏,上面讲了一下,就是说 Mishards 负责将来自客户端的请求拆分,并路由到内部各细分子实例,最后将子实例结果汇总,返回给客户端,对吧?好像跟你刚才描述的不太一致。
顾老师 @Milvus:因为这说的是另外一种情况,就是说是比如说这索引它很大,它有好多的文件,他可能这些文件都落在不同的只读节点上,那么你是需要在所有这些只读节点上都查完一个 top k 最后再做一次合并,你才知道最终的结果。这个其实是我刚才说的第一种情况,就是你要你索引它包含 10 个文件,但是一个机器放不下这种情况。
Attendee C:对,然后还有可能还剩下一种情况,反正就像我刚刚说的分发不同的请求,就是说可能说有不同的 collection,然后它索引,然后比如说有三个集合的索引放在一个节点上,另外几个节点,另外几个的索引放在另一个节点上,实际上他们索引都不是特别大。
现在 Mishards 都是支持的,是吗?还是说我需要定制化的去做一些什么操作,然后才能满足这两个情况?
顾老师 @Milvus:都是支持的。
你之前在 ElasticSearch 上尝试做的图片搜索,你觉得他支持的怎么样?
Attendee C:ES 其实我当时也是测了大概维度比较低,也就 1000 万左右,100 维的这种特征值,实际上速度的话,因为我们单机比较慢,因为我没有做任何的优化,还是比较慢的。
遇到的问题的话也没有特别多,因为它有一个特性,7.6 左右版本,提供了一个两个相应的 vector 数据类型,对吧?然后可能当时考虑的是把这些 vector 这种特征值直接存放到 ES 里面,然后在其他的一些相应的业务数据,我们可能就会用另外的来进行陈述,实际上他们两个之间的关联也是通过一些正如 Milvus 一样的,有一些特定的什么 ID 来进行一些这样的一个关联。
现在主要考虑 Milvus 是因为它像你们这边一些具体的方案都有了,因为还要看有落地的这些方案。然后 ES 这边我们如果要做的话,可能像其他的一些前面的工作,包括做一些自定义 API 什么, 做一些相应的开发任务,还有后面那些具体的当时有没有考虑太细,但是现在目前来看还是打算用你们 Milvus 来做。
我当时做的主要是单机的,没有考虑到分布式这个场景,有可能 ES 那边的分布式场景的话,跟你们这还是有相比的话有一定的优势。
顾老师 @Milvus:ES 它确实本身是有分布式的,但是它的这种关键词型的这种 IVF 索引,就是文本型的索引,它的原理和向量的搜索的原理还是不太一样的,所以这部分分布式能的话能不能带来一个很好的效果,其实可能你们得试过才知道。对。它应该还是能提供一些分布式基本的保证,但对向量的效果这个可能需要自己实测过。
Attendee D:我们其实是做推荐的一些东西的,然后推荐里面可能是召回的一个环节。对召回的话,其实原来它向量确实是可以匹配上的比较好的一种方式,但其实对于业务来说,我们其实还是会对这种标量的过滤有挺强需求的,我想了解一下现在 Milvus 对标量的支持是一个什么样的一个计划?
顾老师 @Milvus:对属性的过滤会在下一个版本里面,具体就是在 0.11.0 版本,按照现在的规划来说。
Attendee D:那它的具体的实现是会像 ES 那样的倒排来做吗?
顾老师 @Milvus:不是,是这样的,就是说从我们的角度来讲,我们也不叫标量了。这两部分结合在一起是向量数据和属性数据,我们称之为属性的数据,那么我们可以允许用户定义一些属性,当然它长度也会有限制,后续我们也会确定一下。然后每一个属性可以是整型的数字也可以是浮点型的数字。然后在搜索的时候是会以向量搜索为主,以向量索引的这个方式,以 ANN (approximate nearest neighbor, 近似最近邻算法)的方式为主,但是 ANN 比如说是一个 IVF 型的索引,他会先去搜寻一个区域的聚类,对吧?我去搜寻这一个区域的聚类里的具体每一条向量的时候,我们这个时候会做一次属性的过滤,这样的话能够确保最终出来的结果一定是比较准确的,是符合你的属性的要求的。然后这个数量也是能够达到,比如说你求 top 10 一定会给你返回 10 条记录,它是经过属性过滤之后的相似性的结果。
Attendee D:就是说它可能还是说是所有的向量都会去扫一遍?
顾老师 @Milvus:它不是一个所有向量都会去扫一遍,因为刚才我讲了他是以 ANNS 的模式为主的。这 ANNS 的模式,比如说 IVF 类的索引,他会首先去计算你搜索向量它所坐落的最近的图形在哪里,然后就图形周围的一片区域看它搜索区域,所以它只会搜索那一小片区域。
先确定你这条搜索向量应该落在索引当中的哪一个聚类当中,然后在聚类周围你可以指定一片区域,它不一定是去聚类的,他说他应该带的聚类那一小个类是可以搜,比如说周围 10 个类这样。对他扫描的那一个子空间里的所有的向量,先做从属性的过滤,然后再去做相似的计算。
| 欢迎加入 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