译者 | 李睿
审校 | 孙淑娟
在正式发布之后,Milvus 2.1增加了许多新功能,例如内存副本、支持字符串数据类型、嵌入式Milvus、可调一致性、用户身份验证和传输中的加密,以提供便利和更好的用户体验。虽然内存中副本的概念对于分布式数据库来说并不新鲜,但它是一个关键功能,可以帮助用户轻松提高系统性能、提高数据库读取吞吐量,并提高硬件资源的利用率。
因此,本文首先解释了内存中的副本是什么以及为什么它很重要的原因,然后介绍了如何在人工智能的矢量数据库Milvus中启用这一新功能。
在了解内存中副本是什么以及为什么这么重要之前,需要先了解一些相关概念,其中包括副本组、分片副本、流副本、历史副本和分片领导者。下图是这些概念的说明。

副本概念
(1)副本组
副本组由负责处理历史数据和副本的多个查询节点组成。更具体地说,Milvus向量数据库中的查询节点检索增量日志数据,并通过订阅日志代理、从对象存储中加载历史数据以及在向量和标量数据之间运行混合搜索,将其转变成为不断增长的片段。
(2)分片副本
一个分片副本由一个流副本和一个历史副本组成,它们都属于同一个分片(即数据操作语言通道,在Milvus中缩写为DML通道)。多个分片副本组成一个副本组。并且副本组中的分片副本的确切数量由指定集合中的分片数量决定。
(3)流副本
流副本包含来自同一DML通道的所有不断增长的段。不断增长的段不断接收新插入的数据,直到它被密封。从技术上讲,一个流副本应该由一个副本中的一个查询节点提供服务。
(4)历史副本
历史副本包含来自同一DML通道的所有密封段。密封段不再接收任何新数据,并将被刷新到对象存储中,将新数据插入到新创建的增长段中。一个历史副本的密封段可以分布在同一副本组内的多个查询节点上。
(5)分片领导者
分片领导者是为分片副本中的流式副本提供服务的查询节点。
启用内存中副本允许用户将数据加载到多个查询节点上的集合中,以便可以利用额外的CPU和内存资源。换句话说,当在集合中加载数据并指定要将其作为两个副本加载时,最终将在两个查询节点上拥有两个数据副本。如果有一个相对较小的数据集,但希望增加读取吞吐量,并提高硬件资源的利用率,则内存中副本的功能非常有用。
在默认情况下,Milvus矢量数据库目前在内存中为每个段保存一个副本。但是,使用内存中的副本,用户可以在不同的查询节点上对一个段进行多次复制。这意味着如果一个查询节点正在对某个段进行搜索,则可以将传入的新搜索请求分配给另一个空闲查询节点,因为该查询节点具有完全相同的段的复制。其好处是不必再次重新加载数据。用户无需执行任何操作,空闲查询节点会自动进行搜索或查询,因为该查询节点已经复制并接收了数据。
此外,如果有多个内存中的副本,可以更好地应对查询节点崩溃的情况。如果没有内存中的副本,则必须等待段重新加载才能继续并在另一个查询节点上搜索。但是,通过内存复制,可以立即将搜索请求重新发送到新的查询节点,而无需再次重新加载数据,如下图所示:

内存中的副本
启用内存中副本的最显著好处之一是整体QPS(每秒查询数)和吞吐量的增加。如果在使用Milvus矢量数据库时启用了内存中的副本,将能够看到系统性能的巨大飞跃。此外,使用内存中的副本,可以维护多个段副本,并且系统在面对故障转移时更具弹性,就像上面的示例一样。
在Milvus矢量数据库中启用内存中副本的新功能很容易。需要做的只是在加载集合时指定所需的副本数量(即调用collection.load( ))。
在下面的教程中,将使用包含书籍信息的集合的示例。假设已经创建了一个名为“book”的集合,并将数据插入其中。然后,可以指定在加载集合数据时要创建的副本数。下面的示例代码将集合加载为两个副本。
from pymilvus import Collection
collection = Collection("book") # Get an existing collection.
collection.load(replica_number=2) # load collection as 2 replicas用户可以灵活修改上述示例代码中的副本数,以最适合应用场景。然后可以直接对多个副本进行向量相似性搜索或查询,而无需运行任何额外的命令。但是,应该注意,允许的最大副本数受到运行查询节点的可用内存总量的限制。如果指定的副本数量超过可用内存的限制,则在数据加载期间将返回错误。
用户还可以通过运行collection.get_replicas()检查其创建的内存中副本的信息。将返回副本组的信息以及相应的查询节点和分片。以下是输出示例:
Replica groups:
- Group: <group_id:435309823872729305>, <group_nodes:(21, 20)>, <shards:[Shard: <channel_name:milvus-zong-rootcoord-dml_27_435367661874184193v0>, <shard_leader:21>, <shard_nodes:[21]>, Shard: <channel_name:milvus-zong-rootcoord-dml_28_435367661874184193v1>, <shard_leader:20>, <shard_nodes:[20, 21]>]>
- Group: <group_id:435309823872729304>, <group_nodes:(25,)>, <shards:[Shard: <channel_name:milvus-zong-rootcoord-dml_28_435367661874184193v1>, <shard_leader:25>, <shard_nodes:[25]>, Shard: <channel_name:milvus-zong-rootcoord-dml_27_435367661874184193v0>, <shard_leader:25>, <shard_nodes:[25]>]>原文标题:Increase Your Vector Database Read Throughput with In-Memory Replicas,作者:Angela Ni
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru