在进行系统的详细介绍之前,我们先来看一组压测结果。从结果中可以看到,第一列向量数量、第三列向量维度和最终的 TPS 呈负线性相关。向量数量、向量维度和索引参数,是影响 TPS 的主要因素,也是我们后面去提升这个性能的主要方向。
我们所做的第一个工作是集群化部署。
从压测数据可以看出,单实例只能支持几百万的向量检索,也就是几十万的视频样本。虽然这种单机部署也会有它的一些优势,比如说部署起来非常简单,使用方便等等。但是对于全局去重的业务不合适的。我们选择使用 Mishards 插件来搭建分布式集群,通过不断地加入 Milvus 实例,来分担每个实例的查询数量,提升整个集群的吞吐量。Milvus 数据库内部处理请求的时候其实都是单线程的,如果要提升整个系统的并发能力,可以考虑右边这样多集群部署方式,提升我们整体的吞吐量。
除了集群化部署之外,创建索引也是提升性能的主要方式。上图左边表示精度,右边表示性能。可以看到,在添加索引之后会导致一些召回率上的损失,nlist 越小,损失越大,所以我们自然想把 nlist 设置得大一些。然而,Milvus 对二值型向量的支持比较弱,在构建索引的时候没有充分利用 CPU 资源,构建时间非常长。比如,nlist 等于 1024 的时候,索引构建时间已经达到一个小时左右。我们就只能妥协地降低 nlist 的大小,给我们带来了召回率上的一些损失。
此外,构建索引期间集群里面的数据无法正常写入的,只有等待整个索引构建完成之后后,才能够正常插入请求,这也是为什么我们需要 Milvus 备级群。我们把向量的读写分为三个状态:正常状态(对主集群进行读写)、索引构建时的状态(不能写入主集群,使用备集群,然后同时查询主集群及备集群)索引构建结束状态(主集群已经可以正常读写,需要把备用集群的数据迁移回主集群,迁移完成后,这个状态也就重新变成了正常的状态)。通过这样主备切换,我们解决了索引构建期间无法正常写数据的问题。