来看看大家都在这次的问答会上问了什么问题!不播放视频也可以看看以下的文字实录喔!
部分Q&A文字实录
* 以下文字部分由语音转文字,已经过一些调整让句意可以更清楚
User:
我现在目前的话是名搜索工程师,我们现在准备在我们的生产环境里加入图片搜索这一个功能,所以在当时技术选型的时候选择了Milvus。
然后因为这个项目在立项的时候是比较晚的,所以我一开始接触的时候是在v0.6.0开始结束,然后我们最近一段时间都在做性能测试和高可用和集群化的一些方案设计,包括混合搜索这样的内容。然后对于性能这方面来说,我们已经有了大概的了解,但是我们现在在一个并发场景下有一些疑问,所以说今天过来问一下。
我们的场景是这样的,我们面对的高并发场景大多是由多个客户端的简单查询而来,就是说NQ大约只有个位数的情况下,然后观察了一下Milvus的工作原理,上次也在群里问过,我们实际上是在一次调用里填入多个搜索向量,然后才在进入方法之后去对它进行做并发处理。这样的话在实际尝试的过程中,我发现好像我们用多个线程、多个客户端去对Milvus服务端做一次测试的话,它的处理好像是串行的,并且它的时间会随着客户端的线程增长而增长。然后这个时候其实在客户端NQ为1的情况下,它的性能已经不是那么符合我们预期了。就是说对于这样的方法,这样的情况,你们会有怎样的一种建议?
顾老师@Milvus:
你的一般的目标的搜索量,比如说你去做图片的话,你的图片库大概会有多呢?
User:
现在目前定在一亿。
顾老师@Milvus:
一亿左右是吗?是这样的,我想你们用的索引类型是IVF类型的索引?
User:
对。
顾老师@Milvus:
好的明白,是这样的,因为其实我们现在也是在做一些性能上的一些调整和一些优化,因为像IVF的索引的话,因为我们是直接集成了faiss的算法,当然我们做了很多工程上的一些改进或者说是一些适配,但是他的一些基础的部分是来自于faiss的一个算法。
那像在NQ1上的时候,其实faiss它并不会去把并发度调得很高,所以这部分其实我们也是发现当中可以有一些优化的部分,现在是在做一些优化。然后但是怎么讲就是一个向量搜索的一个过程,它其实是一个计算量比较密集的过程,包括他在做quantizer的部分,包括他在每个nlist当中去搜索的计算的过程,其实计算量都是要比一般的那种结构化数据库的索引还要更加的耗算力。
所以类似于像IVF这样的索引,你会发现你NQ1搜,你从一亿条里面搜NQ1和一亿条里面搜NQ10,其实它的响应时间可能就增加了那么一点点。但是综合下来的性能,其实你能够跑NQ10或者NQ20是会更划算。所以从这个角度来讲的话,我们也是在想怎么样把这种NQ1的这种小批量的小单次查询,能够稍稍的汇聚成一个小小的微批量,然后再去做,但其实对于硬件成本来说,包括响应时间来说都是一个比较好的均衡,但是怎么讲,在你们的场景当中一亿条的场景当中的话,你们的预期一般来说,你们希望查询在多长时间内能够得到一个反馈?
User:
大约也就在百毫秒左右,100毫秒左右这样。因为我们在前置和后置都会有一些其他的操作,我们会去调用一些AI模型生成向量,然后在Milvus查完之后进行混合检索。
然后总体给出的一个指标时间是300毫秒,但是留给我们中间这一部分大概也就在100毫秒左右。然后实际上测下来用NQ1查的话,确实是不容易划算。然后之前你也提到就是说做一个小的聚集,我们现在目前的思路也是这样,然后想过来近距离接触一下,问一下你们会不会有更好的想法?
顾老师@Milvus:
你的一亿向量的话,大概是什么维度的呢?256维吗,还是512维的?
User:
可以经过优化,但是至少是128维。
顾老师@Milvus:
128维的话,因为我们之前有测一些,比如说sift-1b的这种128维的10亿条的数据,10亿条的数据的话差不多140G, 那128维如果一亿条的话,我估计差不多是在14G服务的内存的占用左右。其实如果底库变动不是特别频繁的话,其实也是可以通过集群的方式做多个组群,然后去增加系统吞吐量。但是在每个节点上肯定是汇聚成一个小小的微批量会更好一些。
然后还有一个我觉得可以潜在尝试的部分,如果这个底库他变动不是特别的频繁,它相对比较稳定的话,也许你也可以尝试一下图索引。但因为图索引它构建的索引时间会比较长。但是他查询速度会比较快,但就是一定要限定在说你们这个东西他不会经常变,那图索引它还是值得去尝试的。不然的话可能就在运行、构建索引这些维护上可能会面临比较大的挑战。
User:
好,可以这边可以去和组里讨论一下,我们还是会进一步去做一些尝试。
然后另外的话我还有一些其他的问题,就是关于一个增量更新的问题。对于我们现在的这种场景来说,我们的增量更新基本上都是小量更新的,但是我们对实时性一会有一些要求,所以说去设定一个index_file_size就变得比较的尴尬。然后如果说我们设定的过小,就会导致索引文件过于碎片,然后如果索引过大的话,就会导致它索引建立的这种间隔会比较长。那么在这之间的话,如果说你曾经有过一种想法,当索引进了落盘之后,它可不可能会被合并?
顾老师@Milvus:
你的意思是索引文件,比如说都按1G大小的建完之后,然后后续再合并成比如说2G大小的这样的一种模式?其实确实我们之前是,甚至现在也一直在想能不能这样去做,因为是这样的,它的这种比如说IVF型的索引的话,其实你的单个索引文件越大,它的搜索性能会越高,因为它的IVF它在计算的过程当中,它quantizer算完之后,他其实这quantizer固定的开销,他可能占得比例是比较大的。如果你的每一个文件都要去算一遍量化的阶段的话,它其实不是那么的划算的,如果你的文件更大,那么你所要计算的量化的步骤就会越少。
那么当你搜索一个大就是搜索一个大的向量集的时候,其实速度会更快,所以我们其实也是一直在想说,怎么能够去合并这些索引文件,但是以现在目前的架构的设计,比如说我1G的新增数据,然后根据这1G新增完了建了一个索引的分片,针对这1G的增量数据,那么当时又有1G数据进来的时候,就在那一集数据上建立了一个相应的索引分片,所以如果说要把这两部分合并的话,其实它是需要把这2G的数据全部都重建,所以在这2G的数据上做整个的一个重建索引了。
因为像IVF的索引的话,他这1G和那1G,他的量化的聚类的信息可能是完全不一样的,所以不能够或者说很难把它直接的去合并,按现在做法的话,如果要合并的话,可能就会重新的去相当于把file size扩大一倍之后再去建这索引,其实我们也在想怎么把这个东西做的更加可行一点,因为他这样去做的话,势必会影响到会需要更多的时间去建这个索引。所以比如说如果你有一个固定的维护的系统维护的窗口,也许比较容易去做这样的操作。但如果你是一个7724,你都需要有一个比较好的在线服务的效果的,要寻找这样的一个窗口去做这个事情,可能就会变得有一些挑战。那么其实还是和你的更新的频率也会很有关系,像你们的系统当中,比如说你的底库是1亿的话,你一般来说每一天会增量进来的东西大概会有多少?
User:
大概也就在万字左右,所以说还是算比较少的。
顾老师@Milvus:
是的。因为确实万级左右确实是是一个比较少,因为怎么讲是因为原来很多设计的场景下面它可能涉及到的一些这种大规模的很多的摄像头的设备的数据汇总进来,所以它每天的增量会比较显著一点,可能几百万几千万这样子。在万级的这种小数据,它有的时候确实会有一点尴尬。
所以在这一部分的话确实因为像现在如果说比如说这万级的数据进来,它不手动触发件强制的建索引的话,他会这几万,比如说就多出这1万条的话,这1万条当中做暴搜的话应该也还好。
但是可能就你一天1万的话,一个星期才7万,所以可能确实需要评估一下,在某个时间点上你需要手动触发建索引。所以确实这个小文件怎么去做的,就是把索引的效率再进一步提升的话,你得看看你们正常流程下,比如说每周有没有一个固定的系统维护的窗口,可以去做一个索引优化的一个动作。
User:
我们现在目前的方式有多自行切换主次这样的方式,来进行这样的事情。大概基本上最大的现在目前在这个阶段遇到的问题就是这两个。然后上面还有一个比较小的问题,如果说进入开发阶段的话,我们可能需要选择一个版本进行长期的维护的。那么像这一次0.6~0.7的更新,其实是一个比较大的变动,并且包括SDK结合也会存在变动。那么在想如果说现在按照这样的迭代频次来说,后续会不会有一种类似于LTS的版本去对外提供支持?
顾老师@Milvus:
其实0.7这个比较重要的更新之后,其实我们会沿着这个大的方向上一个相对来说比较稳定的方式去做一个更新,做一个把功能的叠加。因为确实在我们的项目的初期,可能有些部分设计的不是那么的稳,但是0.7开始的话,我们相对来说是会比较稳定下来的很多部分。其实老金也在这边,应该应该可以说一下,我们这边0.7这条线以后应该会是比较稳定的一个方式,所以我们也是在0.7当中去更新了我们这些术语什么的。
User:
大概了解,因为的确变动的还是挺多的。然后我大概我就这些问题了,下面的时间可以交给其他的同伴一起过来讨论。
老金@Milvus:
刚刚用户问了一个事情,我们这边并发的情况下的性能不是很好的事情。我想问一下用户,咱们这边对于并发的话他希望的qps达到什么程度?
User:
QPS大概每秒就在几百的样子。
老金@Milvus:
每秒几百是吧?
User:
对,我们的qps我们现在目前平台是按照分钟来计算,那么我们在做猜想就是图片搜索调用的频次肯定是比文本语意搜索要少的,那么我们现在文本语义、是从每分钟大概在3000~4000,然后我们做一个折算,大概图片搜索的话,碰到秒级的话也就在一两百左右。
老金@Milvus:
补充一下刚刚顾老师说的一个事,就是我们这边在0.7.0后面会出一个0.7.1的版本,0.701的版本的话,对于 qps这方面的话,包括您前面提到的单条查询的话,性能感觉没有什么太大优势,这方面应该是有一个优化。到时候欢迎关注一下。
User:
好,我一直会持续关注。
15:37 - 20:05
可爱的面试者来与我们学习了,这里就不把内容贴出来了。
顺便插播一则招聘广告,我们现在招聘众多岗位,详情请见 ZILLIZ 官网
User 2:
我这边没有太多可以分享的, 刚入门来学习的。
顾老师@Milvus:
没有关系,我不知道您这边的话,现在主要关注的部分是在什么方面?因为通常来说可能关注到这样的项目的话,可能是和现在工作当中有一些结合?
User 2:
这边主要以图搜图的一些解决方案。
顾老师@Milvus:
对,图片搜索的确实我看到大家现在都对这个东西比较感兴趣,也是在你的就是工作层环境下面,也是会有面对这种图片处理的这种这种场景是吗?
User 2:
对的是的。
顾老师@Milvus:
所以你们的需要去这种处理或者说搜索的图片大概是在什么量级上的?
User 2:
目前大概在1亿左右,整个库亿级的还没有到10亿。
顾老师@Milvus:
明白,确实现在在实际的场景当中,我们了解下来,确实在亿级它是一个比较相对来说比较常见的一个量级。因为原来我们在开发这系统当中,因为和接触到的用户的层面和不同的行业也比较有限,所以我们之前可能都是设定的模式都是一个海量的,比如说10亿级的,然后它的一个搜索性能大概是什么样子的一个过程。但是就像刚才参加者也说到了他们可能是在千万级到亿级,但是希望可能比如说对qps会有更高的要求的这种场景,所以也是因为我们通过开源的这种方式接触到了更多的用户,所以我们也理解了大家更多的需求,我们也是在不断的调整我们的这些我们开发做搭建系统时候的一些倾向性,我们现在的目标就是要把它做得更易用,然后做的更稳定,
然后在能够满足绝大部分的用户的一些需求。我也想问一个问题,在你们的场景下,你们一般都是使用 GPU版的milvus版本,还是在使用CPU版本的milvus?
User 2:
我这边估计以后应该是以CPU为主。
顾老师@Milvus:
好。了解。因为确实虽然我们一直觉得说gpu去建索引它速度会快很多,但是确实我们了解到的,或者说我们接触到很多用户,他可能是需要在一些公有云的环境下,或者说组织内部搭建的私有云的环境下,可能更多的都是在使用CPU的这种docker的镜像。因为可能确实GPU虽然很好,但是GPU虚拟化的技术可能相对来说没有没有单纯CPU的虚拟化的技术那么好,所以大家感觉还是都在以 CPU版本的为主。
CPU版本也是一个在我们0.6.0之前其实都是需要用GPU的,但是开源之后很多人都在问,不断的问我们说我只有cpu的环境能不能运行 milvus这个系统,所以也是在0.6.0当中,我们是做了 CPU的版本的。
那么 CPU版本虽然说它建索引会比GPU版本的慢,但是通过一些集群读写分离的方式也能够去就是说虽然在索引的时候会占满CPU资源,但是并不会影响读节点这样子。对,像诸如此类这种这
需求和一些实际的情况,我们都是在开源了之后,跟大家接触了之后才能够获取到这些信息。
所以我非常希望说我们做这样的活动,也是希望大家都能够使用到milvus,然后也能够让我们了解到你们的一些需求和一些碰到的问题,这样我们就能更有动力和更有方向去改改进我们的这个项目。
User 2:
咨询一个技术问题,我们现在这个能力有没有可能比如说部到公有云上去,去比如说作为公有云的一个能力去提供?
顾老师@Milvus:
其实从技术角度来讲的话,我们现在是在Milvus,其实我们在做一个ann-benchmarks的测试。其实就是上次的,上周的时间的一个讨论当中,我们向大家介绍了一下,说我们现在在做的 benchmark的测试,它其实当中用到的环境就不单单是本地私有化的环境,也包括了阿里云的环境,也包括了微软云的环境,也包括了AWS环境。
其实很多云厂商或者说用户他们本身的环境就是云的环境,所以其实把Milvus部署到云环境下是完全是可以的,包括我们自己后续也在做一些更加可能就会往向量的领域再往上再扩展的一些项目,都也是奔着这种云原生的环境下面去做的。因为包括以后,如果长期来看,我们要提供一个比如说一个服务的话,我们肯定也是在一个云的环境下,或者它是公有云的环境,或者说它是我们自己家的私有云,以现在的方式来讲的话,它必然是一个云的环境。
所以这部分是我们从一开始去开发这个项目的时候,包括我们现在提供的Docker镜像的这种下载,也是都是为了考虑这种情况去做的相应的这种设计。