我们如何设计文件搜索系统?

时间:2019-05-25 20:54:05

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

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

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

enter image description here

我们应该设计具有正确组件的分布式搜索系统的正确方法。

1 个答案:

答案 0 :(得分:1)

好的...这是一个广阔的话题。实际上,elasticsearch正是为此而完成的。但是谷歌也是。从elasticSearch到Google搜索,存在技术差距。

如果您要亲自执行,仍然有可能...但是要做很多工作,要与Elasticsearch一样高效。快速的答案是:使用elasticsearch。

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

TFIDF和余弦距离

如您首先指定的,您将标记化 然后将标记化的文本表示为矢量,然后测量文本与搜索词之间的角距离。

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

的文本

A)“ foo foo foo foo bird bird”将为[4,0,1] 另一个

B)“ foo bar” [1,1,0]

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

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

TFIDF代表术语频率与文档频率成反比。 这将通过评估所有文档中单词频率的倒数来评估文档中单词的频率。它的作用是指向文档中的重要单词。

让我们解释一下:

  • “在……中”等单词无处不在,所以它们并不重要
  • 在您所有的文字中,“语料库”一词的出现频率为不知道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将为您提供复制可伸缩性,分发以及您梦dream以求的一切。

仍有理由不使用elasticsearch:

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

缩放和分发部分

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

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

如果它代表1M的文本,则无需分发。 如果您对像Wikipedia这样的大索引进行索引,则将需要一个分布式的倒排索引(Wikipedia在搜索框中使用了Elasticsearch)

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 Web服务器。我将使用nginx来服务静态页面,并使用netty或vertx之类的东西来进行搜索,然后构建链接到文本的答案(这取决于您在一秒钟内要服务多少用户)

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

对于示例维基百科来说,该文本少于1T。

最终

如果您在一周内使用elasticsearch进行此操作,则可能需要2周并投入生产。如果您自己执行此操作,则需要至少一名高级开发人员和一名数据科学家(一名架构师),并且大约需要一年或更长的时间,具体取决于要索引的文本量。我不禁停止问自己“这是干什么的。”

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

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