我有一个包含数百万个元素的 Redis-Hash,并且不断添加新元素。 在 php 中,我运行无限循环来获取、处理和删除一个元素。 因此,我需要获取任何现有元素的密钥(最好是插入哈希中的第一个元素,FiFo)
while($redis->hlen()) {
$key = ???
// process $key
}
虽然我知道
RANDOMKEY
和 SRANDMEMBER
命令,但我没有找到任何方法来获取哈希的密钥。由于哈希的大小,HGETALL
和HKEYS
也不是一个选项。我需要顺序处理。
感谢帮助。
没有任何技巧可以访问给定哈希对象的随机项(或第一个或最后一个)。
如果您需要迭代哈希对象,您有几种可能性:
第一个是用另一个可以切片的数据结构(如列表或 zset)来补充哈希。如果您仅在散列中添加项目(并迭代以删除它们),则列表就足够了。如果您可以添加/删除/更新项目(并迭代以删除它们),则需要 zset(将时间戳作为分数)。 zset 的两个列表都可以切片(lrange、zrange、zrangebyscore),因此很容易逐块迭代它们,并保持两个数据结构同步。
第二种方法是用另一种支持类似 pop 操作的数据结构来补充哈希,例如列表或集合(lpop、rpop、spop)。您可以从二级结构中弹出所有对象并相应地维护哈希对象,而不是迭代哈希对象。同样,两种数据结构需要保持同步。
第三种方法是将哈希对象分割成许多块。这实际上是内存高效的,因为您的密钥仅存储一次,并且 Redis 可以利用 ziplist 内存优化。
因此,不要将哈希存储为:
myobject -> { key1:xxxx, key2:yyyyy, key3:zzzz }
您可以存储:
myobject:<hashcode1> -> { key1:xxxx, key3:zzzz }
myobject:<hashcode2> -> { key2:yyyy }
...
要计算额外的哈希码,您可以在密钥上应用任何提供良好分布的哈希函数。在上面的示例中,我们假设 key1 和 key3 具有相同的 hashcode1 值,key2 具有 hashcode2 值。
您可以在这里找到有关此类数据结构的更多信息:
应计算哈希函数的输出基数,以便将每个哈希对象的项目数限制为给定值。例如,如果我们选择每个哈希对象有 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
...
因此,您可以逐块迭代,其粒度由哈希函数的输出基数决定。