搜索分片?

时间:2008-11-04 00:06:35

标签: database scalability sharding

简短版

如果我将用户分成碎片,我该如何提供“用户搜索”?显然,我不希望每次搜索都能击中每一个碎片。

长版

通过分片,我的意思是有多个数据库,每个数据库都包含总数据的一小部分。对于(一个天真的)示例,数据库UserA,UserB等可能包含名称以“A”,“B”等开头的用户。当新用户注册时,我会简单地检查他的名字并将他置于正确的位置。数据库。当一个返回的用户登录时,我再次查看他的名字以确定正确的数据库以从中提取信息。

分片与读取复制的优点是读取复制不会扩展您的写入。所有写入主站的写入都必须转到每个从站。从某种意义上说,即使读取负载是分布式的,它们也都带有相同的写入负载。

与此同时,分片并不关心彼此的写作。如果Brian在UserB分片上注册,则UserA分片不需要听到它。如果Brian向Alex发送消息,我可以在UserA和UserB分片上记录该事实。这样,当Alex或Brian登录时,他可以从他自己的分片中检索所有发送和接收的消息,而不查询所有分片。

到目前为止,这么好。搜索怎么样?在这个例子中,如果Brian搜索“Alex”,我可以检查UserA。但如果他用他的姓氏“史密斯”搜索亚历克斯呢?每个碎片都有史密斯。从这里,我看到两个选项:

  1. 让应用程序在每个分片上搜索Smiths。这可以缓慢完成(连续查询每个分片)或快速(并行查询每个分片),但无论哪种方式,每个分片都需要参与每次搜索。与读取复制不会缩放写入的方式相同,搜索每个分片都不会缩放搜索范围。您可能会达到搜索量足够高以淹没每个分片的时间,并且添加分片对您没有帮助,因为它们都会获得相同的音量。
  2. 某种索引本身可以容忍分片。例如,假设我要搜索的字段数量恒定:名字和姓氏。除了UserA,UserB等我还有IndexA,IndexB等。当一个新用户注册时,我将他附加到我希望他找到的每个索引。因此,我将Alex Smith纳入IndexA和IndexS,他可以在“Alex”或“Smith”上找到,但没有子串。这样,您不需要查询每个分片,因此搜索可以是可伸缩的。
  3. 那么可以搜索缩放吗?如果是这样,这种索引方法是否合适?还有别的吗?

5 个答案:

答案 0 :(得分:7)

没有灵丹妙药。

显然,由于您将会产生极高的延迟,因此不可能连续搜索每个分片是不可能的。

所以你想要并行搜索,如果必须的话。

有两个现实选项,您已经列出了它们 - 索引和并行搜索。请允许我详细介绍一下如何设计它们。

您可以使用的关键洞察力是,在搜索中,您很少需要完整的结果集。您只需要第一页(或第n页)结果。因此,您可以使用相当多的摆动空间来缩短响应时间。

<强>索引

如果您知道将搜索用户的属性,则可以为它们创建自定义的单独索引。您可以构建自己的inverted index,它将指向每个搜索词的(shard,recordId)元组,或者您可以将其存储在数据库中。懒惰地,异步地更新它。我不知道你的应用程序要求,甚至可能每晚都重建索引(这意味着你不会在任何一天都有最新的条目 - 但这对你来说可能没问题)。确保优化此索引的大小,以便它可以适合内存;请注意,如果需要,可以对此索引进行分片。

当然,如果人们可以搜索"lastname='Smith' OR lastname='Jones'"之类的内容,你可以阅读Smith的索引,阅读Jones的索引,并计算联合 - 你不需要存储所有可能的查询,只需要他们的建筑部件。

并行搜索

对于每个查询,请向每个分片发送请求,除非您知道要查找哪个分片,因为搜索恰好位于分发键上。使请求异步。获得第一页结果后立即回复用户;收集其余的并在本地缓存,这样,如果用户点击“下一步”,您将准备好结果,不需要重新查询服务器。这样,如果某些服务器的使用时间比其他服务器长,则无需等待它们为请求提供服务。

当您使用它时,请记录分片服务器的响应时间,以观察数据不均匀和/或负载分布的潜在问题。

答案 1 :(得分:2)

我假设你在谈论碎片a la: http://highscalability.com/unorthodox-approach-database-design-coming-shard

如果您阅读该文章,他会详细介绍您的问题,但很长一段时间内,您可以编写自定义应用程序代码,将不同的分片整合在一起。您可以执行一些智能哈希来查询单个分片并将数据插入分片。您需要提出更具体的问题才能获得更具体的答案。

答案 2 :(得分:1)

实际上,您确实需要每次搜索才能命中每个分片,或者至少每个搜索都需要针对包含所有分片数据的索引执行,这些分片归结为同样的事情。

据推测,您根据用户的单个属性进行分片,可能是用户名的哈希值。如果您的搜索功能允许用户基于用户的其他属性进行搜索,则很明显没有单个分片或分片子集可以满足查询,因为任何分片都可以包含与查询匹配的用户。在执行搜索之前,您不能排除任何分片,这意味着您必须针对所有分片运行查询。

答案 3 :(得分:1)

你可能想看看Sphinx(http://www.sphinxsearch.com/articles.html)。它支持分布式搜索。 GigaSpaces具有并行查询和合并支持。这也可以通过MySQL代理(http://jan.kneschke.de/2008/6/2/mysql-proxy-merging-resultsets)完成。

要构建非分片索引类型,首先会破坏分片的目的:-)如果需要分片,集中索引可能无效。

我认为所有分片都需要并行命中。需要对结果进行过滤,排序,排序,分组,并将结果与​​所有分片合并。如果碎片本身变得不堪重负,你必须按常规(重新加工,放大等)来再次破坏它们。

答案 4 :(得分:0)

RDBM不是文本搜索的好工具。看Solr你会好得多。 Solr和数据库之间的性能差异将在100倍的数量级。