- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
直播|Milvus 实战系列 #6 Milvus 在微博内容风控特征工程体系中的实践
展开查看详情
1 .微博大数据算法工程师 胡可
2 .01 业务背景介绍 02 相关流程设计 目录 03 调优与排错 04 问题与建议 05 优化与拓展
3 .业务背景介绍 线上同质相似化场景较多,同质相似特征的价值被低估 微博全站恶意营销,恨国公知等群体发布的文本及图片相似程度很高,但是 一般风控模型多为单一的文本、图片模型,从而会对从属于同一类物料的隐 含同质相似挖掘不足 节假日等流量高峰期数据过检压力大 目前节假日高峰期陡增的文本、图片的过检压力大,需要相似聚类降低数据 量级 搜索场景需求大 因为风控的主要对象是用户相关行为,模型迭代速度有时跟不上恶意用户的 对抗,因此需要历史数据用新模型全量回溯,必然会产生同质搜索 有些线上重模型对系统并发性、实时性支持较弱 目前模型多为NLP语义模型和CV视觉模型,在有些严格实时且高并发的场景 有压力,需要通过特定embedding化的相似来代替已有的重模型
4 .业务背景介绍 部分效果 已上线项(Milvus相关) 项目名称 相似技术栈 微博文本同质化 Milvus v1.1.1 微博图片同质化 Milvus v2.0.0等 全量历史图片搜索 Milvus v1.1.1 用户相似度搜索工具 Milvus v1.1.1 ………. ………..
5 .相关流程设计 同质化相似场景: 过程: 1、将特定的文本、图片通过算法Embedding化 2、预处理所有的Embedding 3、所有Embedding去重写入milvus 4、划分相似主体,确定基库和日活库 5、基于spark计算引擎结合相似逻辑进行判定类 别,然后对类别进行抽样处置
6 .相关流程设计 同质化相似场景: 环境配置: 参数设置: 1、文本同质化项目中,milvus采用mishards集群 1、文本同质化项目中,索引采取IVF_SQ8, 搭建,共六个节点,每个节点380+G内存,100+核 index_file_size为2048,nlist为2048,nprobe为 CPU,包含一个写节点 32,距离度量采用内积(IP),cache_size为30G 2、图片同质化项目中,方案一的milvus v2.0.0采 2、图片同质化项目中,milvus采用K8s部署时, 用K8s部署,datanode 12个pod,broker 15个 索引采取IVF_SQ8,index_file_size为2048, pod 、indexnode 10个pod,querynode 20个pod。 nlist为25000,nprobe为128,距离度量采用内积 采用单独命名空间,总共占集群13%cpu,14%内 (IP) 存 3、图片同质化项目中,milvus采用gpu时,索引采 3、图片同质化项目中,方案二的milvus v1.1.1采用 取IVF_SQ8,index_file_size为2048, nlist为 基于mishards的gpu集群搭建,每个节点四张显 25000,nprobe为128,距离度量采用内积(IP), 卡,每张显卡32G显存 cache_size为60G
7 .相关流程设计 具体实施: 样本向量标准化后去重写入Milvus,写入内容的字段组成为id + Embedding,去重手段是每次插入新向 量前先批量调用删除api删除可能存在的新向量id及Embedding,再执行批量插入,保证milvus库里面的 每个id是最新的Embedding 对于标量过滤条件(比如图片张数、日期等),Milvus v1.1.1版本按照标量枚举并新建分区,Milvus v2.0.0 新建标量字段。在特定的条件筛选时根据特定的分区或布尔表达式选择特定的数据做相似 构建相应的搜索参数,控制nq的大小,以及修改Milvus的配置(比如cache_size、gpu_search_threshold 等),使得最大可能的满足搜索条件 编写udaf函数,对已经相似预聚类的数据进行分组逻辑设计,以降低spark的内存消耗和Milvus长连接的 耗时
8 .相关流程设计 相关效果: 目前入库结果: • Milvus v1.1.1 先写入后搜索,防止边写边读,一天根据相关策略过 滤后的300w 文本Embedding数据与30天接近1亿的Embedding做 相似搜索,耗时40min左右,QPS为1250,查询一条耗时100ms, 每个读节点耗费内存60G • Milvus v2.0.0 根据标量搜索,测试一天10w张图片,与30天接近2 亿的Embedding做过滤后的相似搜索,有性能瓶颈,尤其是flush到 内存时容易卡住,初步测试是10w张图片标量过滤搜索耗时100min 左右,此时querynode有30个pod,而且flush不太稳定 • Milvus v1.1.1 gpu版集群, 四张32G显卡,gpu利用率维持在80% 以上,当下查询qps 5000+,nq是1250
9 .相关流程设计 全量搜索场景: 过程: 1、将文本、图片通过算法Embedding化 2、预处理所有的Embedding 3、所有Embedding去重写入milvus 相关后端接口: 4、从milvus库里面根据id查找对应的向量 5、查找该向量的topN相似,以确定最相似的样本
10 .相关流程设计 全量搜索场景: 流程设计: >> 瓶颈点: 上游数据的QPS很大,且在高峰期会翻倍,在做相似搜索时需要满足高并发,低延 时,效果可以不精准 1、同一个kafka topic采用多个消费者组去消费,一个用来过相关模型生成最新的Embedding, 一个用来实时相似 2、生成的Embedding存入Hbase落盘,根据行键去重,然后每天定时将全量的Hbase数据写入 milvus的对应分区 3、另一个实时流获取id,去Hbase查询对应的向量,然后在milvus里面search做相似判定 环境及参数配置: 1、索引采取IVF_SQ8,index_file_size为2048,nlist为25000,nprobe为128 2、milvus采用mishards集群搭建,共十六个节点,每个节点380+G内存,100+核CPU,包含多 个写节点
11 .相关流程设计 相关效果: 以央视新闻为例,可以看到相似效果良好 1、日活的kafka堆积数据为50k 以下,基本和数据推 送的速度一致 2、Hbase的region数为32个,StorefileSize 400多 G,用户基数为几亿 3、milvus的nq为500,内存消耗120G左右,search 的qps在2000左右
12 .相关流程设计 项目历程及总结: 总体时间线演变 Milvus v1.1.1 Milvus v2.0.0 + k8s Milvus v1.1.1 + gpu 探索流程总结 1. 风控领域的相似和推荐领域的相似场景大致一致,需要在大数据量的情况下具备较高的并发性和实时性和不太高的精确 性,从而需要相似搜索引擎满足基本的增删查改操作、近实时的相似搜索以及可扩展且稳定可靠的要求 2. 过程中需要根据milvus官网和社区的推荐在已知数据量级的情况下进行搜索及部署参数的调整、语言的选型、性能的压 测、以及服务稳定性效果性的测试 3. 做完所有测试后,需要尽可能地适配业务代码、优化资源占用、查询性能和服务稳定性
13 . 几经尝试,为了兼容含有guava等依赖的spark环境、springboot环境, 调优与排错 最终解决方案如下: 依赖冲突: 1、pom.xml里面加入特定版本的protobuf-java(必须是3.11.0)、guava依 赖包 目前项目采用java、python 2、根据milvus-sdk-java的example,加入特定版本的gson、slf4j-api 两种语言进行项目开发 依赖包 Spark项目中引入milvus依赖 3、极其重要!! 因为一些比如spark、spring的子依赖包含guava,且版本不一样,极容 易造成依赖冲突,所以需要通过maven的依赖冲突插件Dependency Analyzer,将每个依赖里面的guava排除掉,然后采用maven-shade- plugin插件,将依赖重命名,防止和线上的依赖冲突 Milvus 内部是 通过 grpc实 现通信 调用的
14 .调优与排错 2、参数设置: nlist 为向量空间点的桶数 相关参数设置: nprobe 为选取的每个桶的最近向量的数量 1、索引选型: gpu_search_threshold 为gpu的搜索阈值,判断nq的情 FLAT 搜索速度非常慢,但是精准度100% 况,决定查询过程在哪进行 IVFFLAT 较前面那个损失了精度即召回率,但是查询速 度快,不过比较耗内存资源(索引数据和原始数据大小相 同) IVFSQ8 解决了IVFFLAT的资源消耗问题,将向量进行 标量量化,进行压缩,但是相较有召回率精度损失 目前所有项目采用IVFSQ8索引,因为有些场景部署milvus 的节点没有gpu 根据对应的nq选择nlist/nprobe = 1024/32的为最佳
15 .调优与排错 gpu版本测试: 方案一: 方案二: 1、配置server_config.yaml 的参数,部署机四张32G 1、分别在一个节点中新建四 显存的显卡 个server_config.yaml 每个 文件指定对应的gpu 2、执行四次docker run命令 时,添加--gpus ‘ ”device=0” ’ 参数,启动四 个容器,开发八组端口映射 3、修改mishards的python源码文件,使其支持管理 节点ip一致但端口不一致的四个milvus服务 4、启动mishards,将索引文件加载到每个gpu显存中 2、docker run命令时,添加--gpus all 参数,开放 两组端口映射
16 .调优与排错 gpu压测效果: 方案一: 方案二: 数据库里面1.3亿数据 用十万条数据测 数据库里面1.3亿数据 用十万条数据测 • 四张卡按照方案一部署的情况,需要30min跑完 nq是 • cpu的 nq为10000时 开的10个并发 qps为33 10000,每张卡的常驻显存为16G,且只有一张显卡利 左右 ,耗费90min 用率70%以上,一张10%以下,其他都是0% • gpu的 nq为10000时 开的10个并发 qps为 • 单选一张32G显存卡,只在一张卡上启动服务,需要 1200左右,耗时83s,且此时每张显卡的常驻 34min跑完, nq也是10000,此时单张显卡的常驻显存 显存为30G,利用率均值为70%以上 为30个G • 可以发现采用多卡多服务并用mishards来管理 • cpu版本时,需要耗时90min,nq是10000 的方式性能提升明显,且只需要几台这样的节 • 所以方案一测试效果和单张显卡的性能差不多,但是比 点就可以满足线上的搜索场景,大大降低了资 cpu版本性能更好 源空闲,提升了显卡利用率
17 .问题与建议 1、建议服务产生的日志文件可以减小小文件数量,配置策略实现定期合并,方便使用方配置在日志服务器中 2、建议开发一个资源计算工具,比如根据数据量级产生推荐的pod扩容方案、内存、显存大小设置、cpu核 数等 因为官方文档上的测试用例所使用的机器型号、详细配置可能和使用方业务上的配置有所差异,从而达不到 高效搜索的性能,也无法定位到是否是资源以外的问题
18 .问题与建议 3、重复id的向量 建议可以设置配置,因为有些场景需要重复的id,有些则必须要去重,通过设置相关配置进行适配不同业务场 景,目前我们使用的去重则是利用了第三方比如hbase的方式或者是先根据要插入数据的id删除数据,再插入 新的同样的数据 4、mishards写节点容易单点故障 如上述去重场景需要批量删除数据和插入数据,也即对写节点进行操作,如果新插入的数据量 很大,则单节点在删除数据时的磁盘数据加载,索引文件加载和创建会很频繁,从而导致节点 负荷太大,容易单点宕机丢失数据,且恢复成本极大
19 .优化与拓展 一些可能可以进行性能优化的设计思路: nlist只是控制的分桶数,如果说有热点且新增的不相似数据全部存入到一个桶里面,会造成在查询搜索时 桶倾斜,如果根据id的hash值或者LSH(局部敏感哈希)算法来将数据文件和索引文件进行hash分桶, 这样能保证数据均匀分布在所有节点上,即使是需要相似的数据在一个桶也能很快根据hash值进行判 定,这样一来对热点数据的搜索健壮性有所加强,且搜索效率没有什么影响 并发搜索能力可以充分利用所插入向量的特点,直接将待所有行数的搜索向量抽象化成矩阵,并在计算相 似度时通过类似矩阵乘法、模糊计算等手段进行相似且搭载GPU进行高性能矩阵运算,而不是在请求端合 并查询请求
20 .优化与拓展 可以有设置相应的并行度的参数,并行度控制每个连接分桶/连接任务将处理多少数据,根据数据集大小来设 置,因为创建多个协程、线程也会耗费大量内存资源 在计算nprobe数量的最相似向量时,可以维护一个数量恒定的优先级队列,基于堆排序的思想进行返回 topn,保证获取的前N个元素的时间复杂度 借鉴倒排索引的思
21 .优化与拓展 拓展 有几个问题: 如果没有调研到milvus引擎工具,对于亿级数据量的相似度搜索,如何去想呢 利用spark做分布式矩阵乘法,矩阵可以横向拆分,可以分布在多个Executor上,然后把待相似向量广播到每个Executor上 即可 相似度计算主体是每个实体的特征向量,如果我们选定了余弦相似度,会不会相对其他相似度有更巧妙的解法? 如果提前把向量归一化,假设基矩阵��1∗� 与待相似矩阵��2∗� ,则��2∗� ∗ ���1∗� 的每个元素即是对应样本与基类样本的相似度 假如说我们有其他替代方案,那为什么最后会选择milvus呢? 源码语言更底层,性能更好,且维护起来相对容易,并且其他方案对数据的增长敏感,会造成资源不足且精度丢失容易跑挂 的情况
22 .
23 .Thank You https://milvus.io https://github.com/milvus-io/milvus 添加企业微信 发送 “直播” 加入交流群 https://twitter.com/milvusio 领取直播PPT + 回放链接 �