【问题标题】:Get random / any value from Redis hash从 Redis 哈希中获取随机/任意值
【发布时间】:2013-06-17 04:36:07
【问题描述】:

我有一个包含数百万个元素的 Redis-Hash,并且不断添加新元素。 在 php 中,我运行一个无限循环来获取、处理和删除一个元素。 因此,我需要获取任何现有元素的键(最好是插入哈希中的第一个元素,FiFo)

while($redis->hlen()) {
    $key = ???
    // process $key    
}

虽然我知道RANDOMKEYSRANDMEMBER 命令,但我没有找到任何获取哈希键的方法。 HGETALLHKEYS 是,由于散列的大小,也不是一个选项。我需要顺序处理。 帮助表示赞赏。

【问题讨论】:

  • 您能否将哈希中的密钥另外存储在一个列表中?那么当你需要获取一个随机哈希成员时,你只需从列表中弹出一个元素,然后从哈希中获取该成员?

标签: php redis phpredis


【解决方案1】:

访问给定哈希对象的随机项(或第一个或最后一个)没有任何技巧。

如果您需要迭代哈希对象,您有几种可能:

  • 第一个是用另一种可以切片的数据结构(如列表或 zset)补充散列。如果您只在散列中添加项目(并迭代删除它们),那么一个列表就足够了。如果您可以添加/删除/更新项目(并迭代删除它们),则需要一个 zset(将时间戳作为分数)。两个 zset 列表都可以切片(lrange、zrange、zrangebyscore),因此很容易逐块迭代它们,并保持两个数据结构同步。

  • 第二个是用另一种支持类似弹出操作的数据结构来补充散列,例如列表或集合(lpop、rpop、spop)。您可以从二级结构中弹出所有对象并相应地维护哈希对象,而不是迭代哈希对象。同样,两种数据结构都需要保持同步。

  • 第三种方法是将散列对象拆分为多个部分。这实际上是节省内存的,因为您的密钥只存储一次,而 Redis 可以利用 ziplist memory optimization

所以不要将你的哈希存储为:

myobject -> { key1:xxxx, key2:yyyyy, key3:zzzz }

你可以存储:

myobject:<hashcode1> -> { key1:xxxx, key3:zzzz }
myobject:<hashcode2> -> { key2:yyyy }
...

要计算额外的哈希码,您可以在密钥上应用任何哈希函数,以提供良好的分布。在上面的例子中,我们假设 key1 和 key3 具有相同的 hashcode1 值,而 key2 具有 hashcode2 值。

您可以在此处找到有关此类数据结构的更多信息:

Redis 10x more memory usage than data

应计算散列函数的输出基数,以便将每个散列对象的项目数限制为给定值。例如,如果我们选择每个散列对象有 100 个项目,并且我们需要存储 1M 项目,我们将需要 10K 的基数。要限制基数,只需对通用哈希函数进行模运算就足够了。

好处是它在内存中会很紧凑(使用 ziplist),并且您可以通过在所有对象上流水线化 hgetall+del 轻松地对哈希对象进行破坏性迭代:

hgetall myobject:0
... at most 100 items will be returned, process them ...
del myobject:0
hgetall myobject:1
... at most 100 items will be returned, process them ...
del myobject:1
...

因此,您可以使用由散列函数的输出基数确定的粒度逐块迭代。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 2017-03-17
    • 1970-01-01
    • 2016-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多