当前位置:  开发笔记 > 运维 > 正文

搜索分片?

如何解决《搜索分片?》经验,为你挑选了1个好方法。

精简版

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

长版

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

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

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

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

    让应用程序在每个分片上搜索Smiths.这可以缓慢完成(连续查询每个分片)或快速(并行查询每个分片),但无论哪种方式,每个分片都需要参与每次搜索.与读取复制不会缩放写入的方式相同,搜索每个分片都不会缩放搜索范围.您可能会达到搜索量足以压倒每个分片的时间,并且添加分片对您没有帮助,因为它们都获得相同的音量.

    某种索引本身可以容忍分片.例如,假设我要搜索的字段数量恒定:名字和姓氏.除了UserA,UserB等我还有IndexA,IndexB等.当一个新用户注册时,我将他附加到我希望他找到的每个索引.因此,我将Alex Smith纳入IndexA和IndexS,他可以在"Alex"或"Smith"上找到,但没有子串.这样,您不需要查询每个分片,因此搜索可能是可伸缩的.

搜索可以缩放吗?如果是这样,这种索引方法是否合适?还有别的吗?



1> SquareCog..:

没有灵丹妙药.

显然,由于您将产生令人难以置信的高延迟,因此不可能连续搜索每个碎片是不可能的.

因此,如果必须,您希望并行搜索.

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

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

索引

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

当然,如果人们可以搜索类似的内容"lastname='Smith' OR lastname='Jones'",您可以阅读Smith的索引,阅读Jones的索引,并计算联合 - 您不需要存储所有可能的查询,只需存储它们的构建部分.

并行搜索

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

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

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有