找回密码
 会员注册
查看: 15|回复: 0

基于Milvus的向量搜索实践(二)

[复制链接]

5

主题

0

回帖

16

积分

新手上路

积分
16
发表于 2024-10-10 12:49:16 | 显示全部楼层 |阅读模式
基于Milvus的向量搜索实践(二) 基于Milvus的向量搜索实践(二) 智搜小贝壳 贝壳智搜 贝壳智搜 我们是来自贝壳找房的工程师,我们热爱技术,热爱算法,我们用技术帮助居住服务者对消费者好,我们持续推进虚拟现实、人工智能、大数据等技术在新居住行业落地。 69篇内容 2020年12月11日 19:10 摘要:此篇为该系列文章第二部分,第一部分主要讲基本概念、背景、选型及服务的整体架构;本部分主要讲针对低延时、高吞吐需求,我们对Milvus部署方式的一种定制;第三部分主要讲实现数据更新、保证数据一致性,以及保证服务稳定及提高资源利用率做的一些事情。1.遇到了哪些问题在项目调研、实施以及最终上线使用过程中,我们遇到了不少的问题,包括:如何解决在满足响应时间的条件下,解决横向扩展的问题。在引擎本身不稳定的情况下,如何实现数据T+1更新时的一致性。在引擎本身不稳定且问题暂时无法明确定位/解决的情况下,如何实现服务的高可用。如何实现资源的动态调整,以提高资源的利用率。2.低时延、高吞吐的要求互联网垂直搜索领域,特别是电商行业,对于特定业务的搜索,热数据的量级一般是可控的(百万级、千万级),一般情况下,对响应时间和整体的吞吐量(QPS)都有比较高的要求。其中,响应时间是首要条件,其次是吞吐量;如果单机在小流量下能满足响应时间要求,但是无法满足吞吐量要求时,集群部署/横向扩展能力,就是一个很自然的解决思路了。3.解决方案3.1 Mishards -Milvus原生解决方案图1 Milvus分布式方案 - Mishards我们可以先了解下Milvus是如何解决低时延、高吞吐问题的。如图1所示,Milvus借助了一个外围服务Mishards来代理Milvus引擎,来实现分布式部署的。处理具体请求的流程大概是这样:请求流量进入Mishards请求队列。Mishards从请求队列中取出请求,借助自身维护的数据段信息,把请求拆分成子请求(只查询部分段),并把子请求分发给负责不同段的Milvus读实例。Milvus读实例处理段请求,并返回结果。Mishards把聚合返回的结果后,最终返回。另外,需要知道的是,Milvus底层的数据存储可以分段存储(不同的数据文件,文件大小可以在配置文件中设定),如果数据量足够大的情况下,数据最终会存储在多个文件中;相应地,Milvus支持对指定文件(可以是多个文件)的查询。由以上分析可知,在数据量比较大的情况下(比如百亿级数据),数据在同一个物理机上无法全部加载到内存中,查询时势必会导致大量的数据加载,从而导致单个查询的响应时间就会让人无法忍受;Mishards刚好就可以满足数据量量大时,单个查询的响应时间提升,使用多个物理资源来分担单个查询的开销。然而,在数据量相对小时,如前面所说的百万级、千万级数据量,在数据的维度比较小时(如500以内),常见的物理机完全可以加载到内存里边。在这种情况下,通过实验发现,分段存储数据反而会使用整体的响应时间变差,因此,我们下面讨论的场景都是数据存储在一个段内。数据存储在一个分段内,当单个查询(小流量查询)响应时间可以满足需求时,我们无法使用Mishards来实现整体吞吐量的增加(因为数据只有一份,而且只能在一个Milvus读实例中被处理,即使我们部署了多个读实例)。那么,在数据只需要存储在一个分段中,而且小流量、响应时间可以满足需求时,如何实现整体吞吐能力的横向扩展呢?3.2 使用envoy+headless service实现扩展由图1可以知道,Mishards实现了读写分离,以及大数据量下单个请求的负载拆分。但是,在互联网垂直搜索领域,特别是电商行业,热数据一般量级并不大,完全可以放在一个分段(文件)中。我们把问题转换成以下两个目标:读写分离读结点可横向扩展对于目标1,其实就是一个请求转发的问题,milvus采用的grpc通信协议,本质上是http2请求,可以通过请求的路径区分开,而且业界已经有比较成熟的工具如nginx,envoy等。所以,问题就集中在如何实现读结点的横向扩展。由于部署采用是是docker+k8s环境,所以尝试采用envoy[2]这个专门为云原生应用打造的方案来解决横向扩展的问题。目标1可以简单解决,envoy配置片段[3]如下:...略...filter_chains:filters:-name:envoy.http_connection_managertyped_config:"@type":type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManagercodec_type:autostat_prefix:ingress_httproute_config:name:local_routevirtual_hosts:-name:backendretry_policy:retry_on:unavailabledomains:-"*"routes:-match:prefix:"/milvus.grpc.MilvusService/Search"route:cluster:milvus_backend_rotimeout:1spriority:HIGH-match:prefix:"/"route:cluster:milvus_backend_wotimeout:3600spriority:HIGH...略...我们可以把实现第二个目标(读结点可横向扩展)细化为两个步骤:1.实现读结点集群部署,并支持增加/减少结点;2.实现请求读结点的负载均衡。1.实现读结点集群部署kubernetes下有一个抽象概念service[4],其含义就对应于域名,我们可以通过将service指向一组Pod(kubernetes下另外一个概念,一个Pod对应一个读结点)[5];我们可以通过kubernetes下的Deployment[6]/Daemonset[7]来管理这组Pod,实现Pod数的增加/减少。另外,我们需要详细分析的是kubernetes是如何进行DNS解析的,具体来讲就是要分析service是如何解析到所对应Pod的ip:port的。由[8]可知,kubernets集群中的每个service,包括DNS服务器,都被分配了一个DNS名,集中的任一Pod可以通过DNS来访问其它Pod。另外,service还分两种,Normal和Headless[9],两种service的的解析方式不同;Normal类型的service会被分配一个DNS的A记录[10],格式如my-svc.my-namespace.svc.cluster-domain.example,该记录被解析到service所对应ip(cluster ip);headless类型的service也会被分配一个相同格式的DNS的A记录[10],但是这个A记录被解析到service指向的一组Pod的ip,客户端可以根据自己的策略来处理这些ip。带着这个问题,我们可以先了解下,kubernetes环境下,请求的转发是如何实现的。由[11]可知,kubernetes借助kube-proxy来实现请求的转发(即到达具体的pod),kube-proxy有三种工作模式user space、iptables、ipvs;详细查看三种模式的实现细节我们可以知道,三者除了设计思路和性能差异之外,流量转发规则没有本质区别(当然,ipvs所支持的策略多些)。2.实现请求读结点的负载均衡在我们已经完成读结点的集群部署并且可以根据配置不同类型的service来实现不同的DNS解析方式前提下,如果我们用envoy作为整体引擎集群的入口,如何实现envoy对Milvus读实例的负载均衡呢?附ipvs所支持的流量转规则rr: round-robinlc: least connection (smallest number of open connections)dh: destination hashingsh: source hashingsed: shortest expected delaynq: never queue当服务暴露的接口是http时,kube-proxy直接就实现了流量的负载均衡,但是,Milvus当前暴露的是grpc接口,在我们的实践过程中,kube-proxy在转发gRPC请求时,并没有实现所预期的负载均衡。我们先了解下grpc的通信机制。gRPC[12]是谷歌开源的,基于Protocol Buffers[13],支持多语言的开发框架、通信框架。由于gRPC是基于长连接进行通信的,在基于域名/DNS来创建连接时,只会创建一个连接(如果对同一个ip:port连续多次创建连接,也会有多个连接)。我们以前面中描述的headless service为例,客户端(即envoy)请求DNS服务器时,会获取一组pod所对应的ip。那么,就剩下最后一个问题,envoy如何创建多个连接呢?由[15]可知,在采用Strict DNS服务发现类型时,envoy会为每一个下游服务对应的ip地址建立一个连接,并且会定时刷新ip地址列表,从而实现了流量的负载均衡。envoy的配置片段[16]如下:clusters:-name:milvus_backend_rotype:STRICT_DNSconnect_timeout:1slb_policy:ROUND_ROBINdns_lookup_family:V4_ONLYhttp2_protocol_options:{}circuit_breakers:thresholds:priority:HIGHmax_pending_requests:20480max_connections:20480max_requests:20480max_retries:1load_assignment:cluster_name:milvus_backend_roendpoints:-lb_endpoints:-endpoint:address:socket_address:address:milvus-ro-serversport_value:19530protocol:TCP至此,实现横向扩展的目的达到,整体的方案如下图2。图2 使用envoy+headless service实现横向扩展4.生产环境多集群部署图3 ALL IN ONE解决了横向扩展的问题,我们就解决服务整体在生产环境的可用性问题。接下来,我们需要考虑如何更方便地部署服务。整体思路如图3,我们使用helm[17]将所有涉及的服务,包括envoy、milvus读、milvus写、mysql(存放milvus的元数据信息)打包成一个chart。最后,我们可以把这个chart放到镜像仓库中(如harbor[18]),以进行集中管理。图3中还涉及到存储部分,包括PVC和glusterfs,其具体实现我们后续详细讲。helm是kubernetes下的包管理工具,支持将一个有复杂结构的应用及所涉及到的所有配置模板化,并打包成一个chart(相当于一个模板),然后可以通过helm安装这个chart(为chart提供所需配置),生成一个release(即一个可用的应用)。5.参考文献https://github.com/milvus-io/milvus/tree/0.11.1/shardshttps://www.envoyproxy.iohttps://www.envoyproxy.io/docs/envoy/v1.11.0/api-v2/config/filter/network/http_connection_manager/v2/http_connection_manager.proto.htmlhighlight=http_connection_managerhttps://kubernetes.io/docs/concepts/services-networking/service/https://kubernetes.io/docs/concepts/workloads/pods/https://kubernetes.io/docs/concepts/workloads/controllers/deployment/https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/https://kubernetes.io/docs/concepts/services-networking/service/#headless-serviceshttps://en.wikipedia.org/wiki/List_of_DNS_record_typeshttps://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxieshttps://grpc.io/docs/what-is-grpc/core-conceptshttps://developers.google.com/protocol-buffers/docs/proto3https://grpc.io/blog/grpc-on-http2/#resolvers-and-load-balancershttps://www.envoyproxy.io/docs/envoy/v1.11.0/intro/arch_overview/upstream/service_discovery#strict-dnshttps://www.envoyproxy.io/docs/envoy/v1.11.0/api-v2/api/v2/cds.proto.htmlhighlight=lb_policyhttps://helm.sh/https://goharbor.io/作者简介下期精彩针对数据更新、保证数据一致性,以及保证服务稳定及提高资源利用率做的相关工作。 预览时标签不可点 工程架构3服务架构7数据架构8工程架构 · 目录#工程架构上一篇基于Milvus的向量搜索实践(一)下一篇基于Milvus的向量搜索实践(三)关闭更多小程序广告搜索「undefined」网络结果
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-29 17:57 , Processed in 0.578177 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表