【问题标题】:Get an object from a bucket in riak without knowing its key在不知道密钥的情况下从 riak 的存储桶中获取对象
【发布时间】:2014-03-21 20:12:41
【问题描述】:

我正在使用 riak 存储桶来存储消息列表,使用 UUID 作为键,使用 json 消息作为值。这工作正常。

我需要一种有效的方法来在不知道其密钥的情况下从存储桶中获取一条消息,至少在以下两种情况之一中:

  1. 获取最后插入的对象(这是我的首选方法)。
  2. 从存储桶中获取一个随机对象(如果第一个选项不可行)。

有没有什么有效的方法可以做到这一点?

我认为另一种选择是检索存储桶中的密钥,然后获取第一个。但这意味着对 riak 进行两次调用,一次获取所有键(仅丢弃除一个之外的所有键),第二次获取对象。好像效率不高。

【问题讨论】:

    标签: riak


    【解决方案1】:

    由于 Riak 是键值存储,因此检索数据的最有效方法是通过键。列出或检索存储桶中的所有键,即使您最终只使用第一个返回的键,也是您可以执行的效率最低的操作之一,因为它会导致 Riak 扫描系统中的所有键(不仅仅是存储桶),并且通常建议不要在生产系统上使用它。

    获取最后插入的对象的最有效方法可能是将 id 存储在不同存储桶中的单独已知记录中。但是,这将要求您在每次插入时执行两次写入,每次读取时执行两次读取,但会以最有效的方式执行。您可以在包含消息的存储桶上实现一个提交后挂钩(必须在 Erlang 中,因为目前无法使用 JavaScript 函数写入记录),以使系统为您执行更新,这将删除需要最后一次写入。

    如果您将大量数据写入包含消息的存储桶,您可能需要调整单独的存储桶,使其不允许多个值并且最后一个值获胜。这样,您将降低由于在系统中频繁更新此单个记录而创建大量同级的风险。这将始终为您提供最后写入的记录之一,但不一定是最后一条(尤其是如果您经常向数据库写入消息),因为 Riak 不支持任何类型的原子性并且是最终一致的数据库。

    如果您使用 leveldb 后端,您还可以创建一个或多个二级索引,并使用它来限制您仅扫描最近的记录,这比扫描所有键更有效。然后,您可以通过 mapreduce 选择最近的密钥或随机密钥,但这会比前​​面描述的方法效率低得多。

    我想不出任何有效的方法来从 Riak 检索存储桶中的随机记录,除非您知道已插入的密钥范围并且可以在客户端上随机决定要获取哪个密钥。一种方法是按顺序生成所有键,而不是使用 UUID,但这在高度并发的分布式系统中自然不是一个好主意。

    【讨论】:

    • 谢谢。我将您的答案标记为已接受,因为它很好地解释了为什么 riak 不是用作队列的最佳工具,或者一般来说,不是对密钥未知的对象进行操作。
    【解决方案2】:

    第一个任务很容易实现:

    • 添加post-commit hook,它将最后插入的密钥写入某个预定义的密钥/存储桶位置
    • 从预定义的密钥/存储桶中获取密钥并使用它们发出获取查询

    这仍然是两个操作,但两者都只是快速获取。加上额外的挂机开销,但也不会太重。

    第二种情况也很简单,但实际使用效率太低:

    • 获取所有密钥(极其昂贵的操作)
    • 随机选择
    • 问题得到

    【讨论】:

    • 谢谢伊万。第一个任务不是那么容易,因为当最后插入的密钥恢复时,我必须删除这个对象,并且一个新的密钥应该作为“新的最后插入的密钥”占据它的位置。我打算或多或少地像队列一样使用这个存储桶。
    【解决方案3】:

    我想出了相同的方案。在我的场景中,我必须保存用户。为此,我需要一个自动增量 ID。所以我所做的是,我将最后插入的密钥放在单独的存储桶中,如“Christian Dahlqvist”所述,每次我想插入新记录时,我都会从该密钥存储桶中获取最后插入的密钥。在这里,我们在该桶中只有一个值,其键为“LastKey”,我们始终知道。我根据获取的密钥增加了密钥,并再次更新了密钥桶。因此,密钥桶中始终包含最新的密钥。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 2015-01-21
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 2018-01-18
      相关资源
      最近更新 更多