Redis - 用于检查集合中是否存在多个值的替代方法

时间:2015-08-03 13:02:44

标签: java 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这样的替代品,但后来我认为这将是一种很好的(hacky)方法来实现它:

> 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"

Redis HMGET页面说明如下:

  

自2.0.0起可用。

     

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

与制作SADD的倍数调用相比,这真的很好,但我真的不确定如果我100%正确,我也不知道使用{{1}是否有任何严重的缺点}} 这条路。

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

4 个答案:

答案 0 :(得分:1)

这当然是一个有效的解决方案,虽然有点浪费,因为你将维护一堆true值 - 一个RAM开销。仅供参考,Redis'集合使用与Hashes相同的哈希表结构在内部实现,所以你不是那么远:)

虽然没有SISMEMBER的可变形式,但它是一个易于编写流程的Lua,因此您可能也想考虑这一点。例如以下内容:

local r = {}

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

return r

答案 1 :(得分: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 REDIS中,execute函数是按以下方式定义:

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

答案 2 :(得分:0)

使用Redisson框架在Java上执行此操作更容易:

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

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

答案 3 :(得分:0)

从 Redis 6.2 开始,您可以使用 SMISMEMBER 命令检查给定集合是否存在多个元素。它将以与请求相同的顺序返回给定元素的数组回复。您可以在客户端获取数组的总和,以获取集合中存在多少这些值。

redis> SADD myset foo bar zet que
(integer) 4
redis> SMISMEMBER myset foo bar not
1) (integer) 1
2) (integer) 1
3) (integer) 0