2016-09-15 29 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接口。因此你不需要使用鍵/連接/序列化來處理。這一切都是由雷森森完成的。