2016-09-15 40 views
1

我在redis的高速缓存的地图具有以下结构:Redis的数据检索

缓存条目:Map<String, Map<String, String>>

内地图可以具有多达25000元件/桶。 有没有办法在redis中从内部映射中检索基于键(redis键,外部映射的键和内部映射的键)的特定值,而无需在访问此redis缓存的Java方法中获取整个redis条目?

目前,如果我不得不删除从内部地图的特定按键,我做它通过以下方式:使用Lua

Map<String, Map<String, String>> mapFromRedis = redis.get("myRediscacheKey"); 
Map<String, String> innerMap = new HashMap<>(); 
if (!mapFromRedis.isEmpty()) { 
    innerMap = mapFromRedis.get("key"); 
} 
if (innerMap.containsKey("keyToBeDeleted")) { 
    innerMap.remove("keyToBeDeleted"); 
    mapFromRedis.put("key", innerMap); 
} 
redis.set("myRediscacheKey", mapFromRedis); 

回答

0

你可以写一个​​(UDF),它装入的Redis和呼叫它来自Java中的Redis客户端。

UDF到Redis/NoSQL DB是存储过程与关系数据库的关系。

所以,你的情况你就必须做这样的事情(伪代码不LUA),

function custom_delete_method(key, outer_map_key, inner_map_key) { 
    inner_map = key.get(outer_map_key) 
    if (inner_map.get(inner_map_key) != null) { 
     delete inner_map.get(inner_map_key) 
     return true 
    } 
    else 
     return false 
    } 
0

你的数据结构具有3级映射:Redis的关键外地图密钥内部地图密钥。从您的示例中,我们可以得到以下映射:myRediscacheKey -> key -> keyToBeDeleted -> value

但是,Redis最多只能有2级映射,即HASH。为了实现你的目标,你必须做压缩的3级映射到2级映射,甚至1级映射。

压缩到2级映射

您可以使用外部映射键作为HASH的关键结合Redis的重点,并采取内部地图密钥作为HASH领域。通过这种方式,我们可以得到如下的2级映射:myRediscacheKey:key -> keyToBeDeleted -> value

// set inner map key 
hset myRediscacheKey:key keyToBeDeleted value 
// remove inner map key 
hdel myRediscacheKey:key keyToBeDeleted 

压缩到1级映射

您还可以在3个键组合成一个键:myRediscacheKey:key:keyToBeDeleted -> value

// set inner map key 
set myRediscacheKey:key:keyToBeDeleted value 
// remove inner map key 
del myRediscacheKey:key:keyToBeDeleted 
+0

我们是否真的需要修改缓存的逻辑结构(OP中的映射Map),以使操作更高效?将困难的工作转移到UDF更容易,并保持您的代码完好无损。如果UDF无法放在Redis实例上(由于某些限制),您应该首选解决方案 – kgdinesh

+0

@kgdinesh这取决于OP想要实现的内容。完整的代码或更好的性能?由于OP提到内部地图中有25000个元素,我认为他可能需要更好的性能。另外,lua脚本执行一些复杂的工作并不是一个好主意,可能会阻塞Redis很长一段时间。 –

+0

做复杂的事情正是为什么UDF的目的不是吗?为什么会阻止redis?通过客户进行类似的呼叫有什么不同? – kgdinesh

0

您可以轻松地Redisson做到这一点。它允许通过由Redisson处理的特殊引用对象将Redis对象引用到另一个Redis对象。以下是代码示例:

RMap<String, RMap<String, String>> mapFromRedis = redisson.getMap("myRediscacheKey"); 

// Redisson loads only small reference object 
// to another Redis map and NOT entire map 
Map<String, String> innerMap = mapFromRedis.get("key"); 

if (innerMap.remove("keyToBeDeleted") != null) { 
    // key has been deleted 
} 
// or with faster approach 
if (innerMap.fastRemove("keyToBeDeleted") == 1) { 
    // key has been deleted 
} 

就是这样!您不需要对每个内部地图更改执行大量更新。引擎盖下它的工作原理只用2操作过的Redis:gethdel

RMap扩展标准的Java MapConcurrentMap接口。因此你不需要使用键/连接/序列化来处理。这一切都是由雷森森完成的。