黄伟,趋势科技(中国)资深研发工程师
前期调研
趋势科技(TrendMicro)是一家全球领先的信息安全软件公司,专为全球软件厂商及个人用户提供安全解决方案。本文作者目前负责构建移动安全 APP 和开发基础设施。工作流程为爬取 Google play 等平台上的外部 APK (Android application package,即 Android 应用程序包),运用趋势科技的算法检测出携带病毒的 APK。使用 Milvus 在趋势科技 APK 库中对携带病毒的外部 APK 进行相似性检索。如发现外部携带病毒的 APK 与库中 APK 相似,需要及时通知企业与个人用户相关的病毒信息。
上述工作要求系统高效检索相似 APK。由于项目前期的 APK 样本数量不大,团队可以利用 SQL 语言在 MySQL 中进行 APK 相似性检索。但随着 APK 样本数量急剧增大,使用 MySQL 无法保证性能,因此团队开始探索新的解决方案。
Faiss
Facebook 于 2017 年发布了 Faiss 算法库。Faiss 能快速检索相似向量,还提供 IndexFlatL2、IndexFlatIP、HNSW、IVF 等多个索引,可以解决大部分相似性检索的问题。
但是 Faiss 只是一个基础算法库,存在如下问题:无法管理向量数据、不具备高可用性、缺乏监控手段、缺乏分布式方案、缺少各种语言版本的 SDK 等。
基于 Faiss 等近似最近邻搜索(Approximate Nearest Neighbor Search, ANN)算法库开发插件
行业内基于 Faiss、NMSLIB 等近似最邻近算法库开发了一些插件,例如以 Faiss、NMSLIB 作为底层库开发的 ES (Elasticsearch) 插件,如下图所示:
此类解决方案的优势在于无需额外写一套分布式代码。由于 ES 插件已经非常成熟,用户能够快速掌握提供 ES 的 DSL。一套 ES 能够同时检索文本和向量,而且支持标量字段过滤。
目前阿里、网易、亚马逊都采用此类解决方案。京东也基于 Faiss 开发了一套分布式系统 Vearch,但目前 Vearch 仍处于起步阶段且社区并不活跃。
此类解决方案的问题在于消耗内存大,且不易于性能调优。为获取最佳性能,需要进行 segment 合并。
Milvus
使用 C 语言开发的 Milvus 开源向量相似度搜索引擎在众多主流方案中脱颖而出。Milvus 与其他方案的对比情况如下图所示:
对比分析可知 Mlivus 性能好,具备以下优点:
- 集成了 Faiss、NMSLIB、Annoy 等主流向量索引库。
- 提供了一整套简单直观的 API,可以针对不同场景选择不同的索引类型。
- 在高可用、分布式以及监控方面有相对成熟的解决方案。
- 用户较多,社区活跃,目前 star 数超过 5000。
趋势科技最终决定选择 Milvus 作为内部的向量检索组件。
项目背景和架构设计
目前趋势科技在 MySQL 中存储了千万级的 APK 样本数据,且每日增量达数十万。算法团队针对 APK 的不同部分抽取计算出其 Thash 特征值,用于相似性检索。团队还会利用不同的 Sha256 算法将 APK 视作二进制文件,根据字节流 hash 分别计算出多个 256 bit 长的 Sha256 哈希值,用于区分不同的 APK。不同 APK 的 Sha256 哈希值不同。每个 APK 的 Thash 特征值对应多个不同的 Sha256 哈希值。
简而言之,Sha256 哈希值仅用于区分不同 APK,而 Thash 特征值用于相似性检索。相似的 APK 可能会产生相同的 Thash 特征值,但 Sha256 哈希值不同。
目前,趋势科技需要开发一套系统,检索相似的 Thash 特征值,并返回此 Thash 特征值对应的多个 Sha256 哈希值,最终检索出相似的 APK。在此过程中,趋势科技需要开发存储和检索 Thash 特征值的功能。在 Milvus 的支持下,趋势科技团队只需将 Thash 特征值转化成二值型向量,并存储在 Milvus 中即可。
检索出相似向量后,团队还需要在 MySQL 中查询 Thash 特征值对应的多个 Sha256 哈希值。趋势科技在架构设计中增加了缓存 Redis 来存储 Thash 特征值和 Sha256 哈希值的映射,以减少查询时间。架构如下图所示:
Milvus 支持多种向量的距离计算方式和索引类型,如下图所示:
趋势科技将 Thash 转化成二值型向量存储在 Milvus 中。为配合业务方,趋势科技采用汉明距离计算不同向量的 ANN 距离。
据了解,Milvus 未来版本会增加 string 类型 ID。此功能的发布可以免去缓存 Redis,简化当前架构。
目前,趋势科技采用上云方案,很多任务都部署在 Kubernetes 上。为实现向量检索的高可用,我们选择了 Mishards——一个用 Python 开发的 Milvus 集群分片中间件,如下图所示:
趋势科技采用 AWS 提供 EFS (Elastic File System) 来存储实际的向量数据。这种存储和计算分离的的做法将成为趋势。此外,趋势科技可以借助 Kubernetes 启动多个读节点,并基于这些读节点创建 LoadBalancer 类型的服务,保证一个或多个节点无法使用时整个集群依旧可用。
最初,Milvus 的架构为单节点,而非贯穿始终的分布式系统。出于对一致性的考量,Milvus 目前只支持一个写节点。但在未来,分布式 Milvus 将改进这一问题。
监控和警报
Milvus 基于 Prometheus 搭建监控系统,使用开源的时序数据分析及可视化平台 Grafana 展示各项性能指标。
使用 Prometheus 监控、存储性能指标:
- Prometheus Server:收集和存储时序数据
- Client 代码库:定制监控指标
- Pushgateway:推送指标数据,确保 Prometheus 可以获取生命周期短且难以被及时提取的监控指标
- Alertmanager:实现报警机制
监控指标较全面,包括:
- Milvus 性能指标
- 系统运行指标:CPU/GPU 使用状况
- 网络、磁盘读取等指标
- 硬件存储指标:数据大小,数据文件及存储情况等指标
系统运行效果
目前,趋势科技基于 Milvus 搭建的 ThashSearch 服务已上线数月。完整链路查询的平均延迟在 95 毫秒以内,具体表现如下图所示:
整体结果达到当初设计时制定的目标。数据导入速度也很快。导入300 万条192 维向量数据大约只需要 10 秒。