2015-08-03 186 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"))) { 
    // ... 
} 
相關問題