2015-08-03 231 views
2

在我的应用程序中,我需要一组值,我需要检查在Redis中设置的中有多少个这些值。Redis - 替代检查集合中是否存在多个值

只是为了简单起见,我想要做的是一样的东西:

> Sadd myset field1 
(integer) 1 
> Sadd myset field2 
(integer) 1 
> Sadd myset field4 
(integer) 1 

> Sismember myset field1 field4 // which is not possible as of now. 

既然不能给多个参数SISMEMBER,我可能要多Redis的调用,这是非常耗时。

我还想着像pipelining的替代品,但转念一想,这将是实现它的一个很好的(哈克)的方式:

> Hset myhash field1 "true" 
(integer) 0 
> Hset myhash field2 "true" 
(integer) 0 
> Hset myhash field4 "true" 
(integer) 1 

> Hmget myhash field1 field2 field3 
1) "true" 
2) "true" 
3) (nil) 

> Hmget myhash field1 field2 field3 field4 
1) "true" 
2) "true" 
3) (nil) 
4) "true" 

RedisHMGET页说以下内容:

可自2.0.0。

时间复杂度:O(N),其中N是被请求的字段的数量。

相比,使倍数呼吁SADD的时候,但我真的不知道如果我是100%正确的,我也不知道是否有使用hmget这样的任何严重的缺点,这是非常好的。

所以我只是想用hmget这种方式的缺点和更好的方法来解决这个问题。

回答

1

这无疑是一个有效的解决方案,虽然有点浪费,你会保持一堆true值 - 一个RAM的开销。仅供参考,Redis的套件内部使用与哈希相同的哈希表结构实现,所以你不是那么遥远:)

虽然SISMEMBER没有可变参数形式,但它作为一个易于编写脚本的流程与Lua你也可以考虑这一点。例如如下所示:

local r = {} 

for _, m in pairs(ARGV) do 
    r[#r+1] = redis.call('SISMEMBER', KEYS[1], m) 
end 

return r 
+0

谢谢你的答复,但我不能以编程方式做到这一点? (我真的想从'Java'做到这一点) – Karthik

+0

当然你可以 - Redis的Lua脚本可以从Java调用完美。阅读您的客户(Jedis?)文档。 –

+0

是的,杰迪斯。其实我正在使用Spring Data Redis。我会检查如何做到这一点。 – Karthik

1

继@itamar的回答,我能够使用lua脚本来做到这一点。

我用下面的脚本:

local r = {} 
for i, m in pairs(KEYS) do 
    r[i] = redis.call('SISMEMBER',ARGV[1],m) 
end 
return r 

可能这将是有用的人在未来,所以才写了如何从javaSpring Data Redis 1.5.0 & jedis 2.6.2)调用此脚本

redisTemplate.opsForSet().add("mySet","3"); 
    redisTemplate.opsForSet().add("mySet","4"); 
    redisTemplate.opsForSet().add("mySet","35"); 
    redisTemplate.opsForSet().add("mySet", "6"); 
    List<String> list = new LinkedList<>(); 
    list.add("1"); 
    list.add("2"); 
    list.add("3"); 
    list.add("35"); 
    list.add("6"); 
    System.out.println(redisTemplate.execute(script, list,"mySet")); 

打印以下内容:

[0, 0, 1, 1, 1] 

编辑我不知道每个人都在说,mySet是KEYS和list是ARGV,但在SPRING DATA REDISexecute功能是这样定义的:

public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) { 
    return this.scriptExecutor.execute(script, keys, args); 
} 
+0

我不确定这是怎么工作的 - 你在KEYS上循环,但它只有一个元素在数组中('mySet')... –

+0

@ItamarHaber执行函数需要'List of Keys'和参数。可能这是'Spring Data Redis'特有的,我没有直接尝试'Jedis'。 ('mySet'是集合名称) – Karthik

+0

这就是常规行为 - 我指的是你的Lua对你提供脚本的单个键执行'for'循环。 –

0

下面是更简单的方法来做到这一点的爪哇与Redisson框架:

RSet<String> set = redisson.getSet("mySet"); 

// uses lua-script under the hood 
if (set.containsAll(Arrays.asList("obj1", "obj2", "obj3", "obj4"))) { 
    // ... 
}