【问题标题】:How can we design system for document search?我们如何设计文档搜索系统?
【发布时间】:2019-10-12 00:00:11
【问题描述】:

最近有人问我一个系统设计问题,我需要“设计文档搜索系统”,我首先想到的是弹性搜索的工作原理。所以我想出了用于支持文本搜索的倒排索引方法。倒排索引对每个术语都有一个记录。每条记录都有出现该术语的文档列表。文档由整数文档 ID 标识。文档 ID 列表按升序排序。

所以我在下面说了一些话,但我不确定这是否应该以分布式方式工作,因为我们可能有很多文档要索引,所以我们需要一些负载平衡器,并且我们需要以某种方式对倒排索引进行分区或数据。意思是一个将上传文档的过程,然后是什么过程将它标记化(它只是一台机器还是一堆机器)。基本上想了解用适当的组件设计这样的系统的正确方法是什么。我们应该如何在系统设计面试中谈论这个?对于这个问题,我们在面试中应该接触哪些内容?

我们应该用正确的组件设计分布式文档搜索系统的正确方法是什么。

【问题讨论】:

    标签: full-text-search information-retrieval system-design inverted-index


    【解决方案1】:

    好的...这是一个广泛的主题。实际上,elasticsearch 正是为此而做的。但是谷歌也是。从 elasticSearch 到 google 搜索存在技术差距。

    如果您进行个人实施,它仍然是可能的……但是要像 elasticsearch 一样高效,还有很多工作要做。快速回答是:使用弹性搜索。

    您可能很好奇,或者出于某种原因您可能需要自己编写它。那么它是如何工作的:

    TFIDF 和余弦距离

    正如您首先指定的那样,您将标记化 然后你将标记化的文本表示为向量,然后测量文本和搜索词之间的角距离。

    想象你的语言中只有 3 个单词“foo, bar, bird” 所以带有“foo bar bird”的文本可以用vector3 [1,1,1]表示 带有

    的文本

    A) "foo foo foo foo bird" 将是 [4,0,1] 另一个

    B) "foo bar" [1,1,0]

    如果您搜索由 [0,1,0] 表示的“bar”,您将寻找具有最小角距离的文本,如果您计算搜索和 BI 之间的角距离,则认为这是 90 °低于A。

    实际上,语言超过 3 个单词,因此您将在更多维度的向量中计算距离,因为 1 个世界 = 1 个维度 :)

    TFIDF 代表词频逆文档频率。 这通过该单词在所有文档中的频率的倒数来评估文档中单词的频率。它的作用是指出文档中的重要单词。

    让我们解释一下:

    • “that, in a the”等词无处不在,因此它们并不重要
    • 在您的所有文本中,“语料库”一词的频率为我不知道 0.0001%
    • 在特定文本中被引用 5 次,其频率为 0.1%
    • 那么它在语料库中非常罕见,但在您的文本中比较重要
    • 因此,当您搜索“语料库”时,您想要首先获得它出现 4 次的文本。
    • 因此,您将获得一个相对出现频率的向量,而不是出现次数的向量,例如 [0.2,1,0.0005]

    https://en.wikipedia.org/wiki/Tf%E2%80%93idf

    最后我给你一个小惊喜:这就是背后的原因 elasticsearch中的评分https://www.elastic.co/guide/en/elasticsearch/guide/current/scoring-theory.html

    此外,elasticsearch 还将为您提供复制可扩展性、分布以及您梦寐以求的任何东西。

    仍然有理由不使用弹性搜索:

    • 研究目的
    • 您实际上编写了另一个搜索引擎,例如 duckduck go(为什么不)
    • 你很好奇

    缩放和分布部分

    https://en.wikipedia.org/wiki/Apache_Lucene之前阅读lucene

    它很大程度上取决于要索引的文本量和单词。

    如果它代表 1M 的文本,您不需要分发它。 如果你索引像维基百科这样的大东西,你将需要一个分布式倒排索引(维基百科使用弹性搜索作为搜索框)

    foo 在文本 A、B、C、R 中 所以我会分区我的索引

    我将使用带有单词作为键的分布式缓存和指向向量的指针列表作为值。我会将值存储在内存映射文件中。 搜索引擎是必须快速的东西,所以如果你自己做这件事,你会减少外部库。你将使用 c++

    在 google,他们最终会遇到向量占用大量空间以致需要将它们存储在多台机器中的情况,因此他们发明了 GFS,这是一个分布式文件系统。

    多维向量之间的余弦距离计算非常耗时,所以我将在 GPU 中进行计算,因为 GPU 对矩阵和向量的浮点运算非常有效。

    实际上,要重新实现所有这些期望你有充分的理由这样做有点疯狂,例如一个非常好的商业模式:)

    我可能会使用 kubernetes docker 和 mesos 来虚拟化我的所有组件。如果需要大容量,我会寻找类似于 GFS 的东西。 https://en.wikipedia.org/wiki/Comparison_of_distributed_file_systems

    您需要取回文本,因此我将使用任何可扩展为任何语言的 NIO 网络服务器。我将使用 nginx 来提供静态页面以及 netty 或 vertx 之类的东西来获取搜索,然后构建文本链接的答案(这取决于你想在一秒钟内服务多少用户)

    如果我打算索引比维基百科更大的东西,所有这些。如果我打算发明比 elasticsearch 更好的东西(艰巨的任务祝你好运)

    例如 wikipedia,这少于 1T 的文本。

    终于

    如果您在一周内使用 elasticsearch 完成,则可能需要 2 周并投入生产。如果您自己做,您将需要至少 1 名高级开发人员和一名数据科学家、一名架构师,并且需要一年或更长时间,具体取决于您要索引的文本量。我忍不住问自己“这是为了什么”。

    实际上,如果您阅读了 lucene 的代码源,您将确切地知道您需要什么。他们做到了,lucene是elasticsearch的引擎。

    Twitter 正在使用 Lucene 进行实时搜索

    【讨论】:

    • 感谢您分享您的想法。我想了解的另一部分是从系统设计的角度来看,我将拥有哪些组件应该以分布式方式完成这项工作?基本上是为了帮助面试官了解每个组件的作用。
    • 谢谢。这将帮助我给出一个广泛的想法,我们应该如何设计一个这样的系统来完成这项工作以及每个组件的基本职责是什么。由于我现在了解了基础知识,因此更广泛的组件设计将为我提供清晰的画面。
    • 如果你是一个研究实验室......是的,你可能需要所有这些组件,如果我不知道确切的需要,我可以给你一个架构的模糊性质。
    • 如果您是一家企业,您将只需要 3 个组件,一个用于收集文档并将它们插入到 elasticsearch 中,另一个用于返回它们,以及 elasticsearch 本身。
    猜你喜欢
    • 2012-06-14
    • 2017-07-08
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    相关资源
    最近更新 更多