【问题标题】:"Fan-out" indexing strategy“扇出”索引策略
【发布时间】:2014-05-23 21:41:14
【问题描述】:

我打算将 Elasticsearch 用于一种社交网络平台,用户可以在其中发布“更新”、与其他用户成为朋友并关注他们朋友的动态。基本且可能是最常见的查询将是“获取我关注的朋友与我分享的帖子”。这个查询可以通过额外的约束(如标签或地理搜索)来增强。

我了解到,社交网络通常采用写入时扇出的方法向关注者传播“更新”,因此查询更加本地化。所以我可以看到 2 个潜在的索引策略:

  1. 将所有帖子存储在单个索引中并搜索 (1) 与请求者共享的帖子和 (2) 其作者在请求者关注的用户列表中的帖子(“幼稚”方法)。
  2. 为每个用户创建一个索引,注入关注用户创建的帖子并直接在该索引中搜索(“扇出”方法)。

从搜索的角度来看,第二个选项显然更有效,尽管它带来了同步挑战(例如,当我停止关注朋友时需要删除帖子)。但我最关心的是指数的乘法;在(成功的)社交网络中,我们可以预期至少有成千上万的用户......

所以我的问题是:

  • ES 如何处理大量索引?会导致性能问题吗?
  • 对于针对我的特定用例的更好的索引策略有什么想法吗?

谢谢

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    每个 elasticsearchindex shard 是一个单独的 Lucene 索引,这意味着几个打开的文件描述符和内存开销。通常,即使在将每个索引的分片数量从默认 5 减少之后,在 index-per-user 场景中的资源消耗也可能太大。

    很难给出具体的数字,但我的猜测是,如果您坚持每个索引使用两个分片,则每台 m3.medium 机器最多可以处理 3000 个用户,这在我看来是令人望而却步的。

    但是,您不一定需要为每个用户设置专用索引。您可以使用过滤别名来为多个用户使用一个索引。从应用程序的角度来看,它看起来像每个用户的场景,不会产生上述开销。有关详细信息,请参阅此video

    话虽如此,我不认为 elasticsearch 特别适合 fan-out-on-write 策略。但是,它是在读取时扇出场景中采用的非常好的解决方案(类似于您在 (1) 中概述的内容):

    • 使用 elasticsearch 的最大优势是您能够执行相关性评分,通常基于一些时间特征,例如浏览上下文。使用 elasticsearch 仅检索按时间戳排序的文档意味着您没有利用它的潜力。同时,Redis 等解决方案将为您提供出色的读取性能来完成此类任务。

    • 写入时扇出场景意味着每次更新都会有大量写入(尤其是如果您的用户有很多关注者)。 Elasticsearch 不是数据库,也没有针对这种使用模式进行优化。但是,它已为频繁读取做好了准备。

    • Fan-out-on-write 还意味着您通过复制有关帖子的信息来生成大量“额外”数据。要将这些数据保存在 RAM 中,您只需要存储元数据,例如在单独的文档存储和标签中的文档 ID。同样,除了 JSON 之外,还有其他格式可以有效地存储和搜索这种结构化数据。

    在这两种情况之间进行选择是关于您的要求的问题,例如平均关注者数量、几乎每个人都关注的“中心”数量、Feed 是否自然排序(例如按时间)等。我认为决定是否使用 elasticsearch 需要是此分析的结果。

    【讨论】:

    • 感谢您的详尽回答!所以 ES 节点在面临内存压力或缺少文件描述符时不会卸载/关闭 LRU 索引?
    • 据我所知。我认为您需要自己关闭它们(这将释放 RAM 和文件描述符)。
    猜你喜欢
    • 1970-01-01
    • 2013-07-25
    • 2012-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2018-07-23
    • 2010-09-30
    相关资源
    最近更新 更多