解決Java Redis刪除HashMap中的key踩到的坑

現象

Java使用Redis刪除HashMap中的key時,取出對應的HashMap後通過Java中HashMap的remove方法移除key然後重新調用redis的Hmset方法將覆蓋無效

示例代碼

//通過key取出對應的HashMap
Map<String, String> ruleMap = jedisCluster.hgetAll("HashKey");
//通過java中移除HashMap中的Key
ruleMap.remove("ruleA");
//將移除後的HashMap重新存入redis的hashmap中
jedisCluster.hmset(key, ruleMap);
//問題來瞭,這裡通過HashKey從redis中取出HashMap時發現ruleA的key的內容還在存在
Map<String, String> newRuleMap = jedisCluster.hgetAll("HashKey");
System.out.println(newRuleMap);

解決方案

通過hdel命令刪除指定HashMap中指定Key:

使用HDEL key field [field …]:

刪除哈希表 key 中的一個或多個指定域,不存在的域將被忽略

示例代碼

//通過redis中針對hashmap移除指定key函數進行處理
jedisCluster.hdel("HashKey", "ruleA");

原理

redis中的散列表在進行存儲值時,隻會將客戶端上送的hashmap中存在的key在redis中查找對應的key值進行覆蓋重寫,

至於通過Java代碼對該HashMap進行的remove操作在redis中並不會感知到,

所以在通過HMSET函數進行操作時,redis隻會找到key覆寫,不會執行del操作,實際針對redis中的hashmap key的刪除隻能通過HDEL函數

示例代碼

我們通過Jedis包中 redis.clients.jedis.BinaryClient.hmset方法的源碼來看,最終發往redis服務器執行的命令時的操作

//實際上在發往redis執行命令前,會將HashMap中的轉成字節數據集合
public void hmset(byte[] key, Map<byte[], byte[]> hash) {
  List<byte[]> params = new ArrayList();
  params.add(key);
  Iterator i$ = hash.entrySet().iterator();
  while(i$.hasNext()) {
    Entry<byte[], byte[]> entry = (Entry)i$.next();
    params.add(entry.getKey());
    params.add(entry.getValue());
  }
  this.sendCommand(Command.HMSET, (byte[][])params.toArray(new byte[params.size()][]));
}

實際對應的redis命令即為:

redis 127.0.0.1:6379> HSET HashKey "ruleA" "valA" "ruleB" "valB"

補充:redis整體刪除,整個hash刪除,批量刪除,單個刪除,正則刪除

對於redis的hash數據結構的刪除:

pool = redis.ConnectionPool(host='127.0.0.1',port=6381,db=0,decode_responses=True)
r = redis.Redis(connection_pool=pool)
pool = redis.ConnectionPool(host='127.0.0.1',port=6381,decode_responses=True)
r = redis.Redis(connection_pool=pool)
r = redis.Redis(host='127.0.0.1',port=6381,db=0,decode_responses=True)

以上三種連接數據庫的方式都測試過有效,主要是後面的decode_responses參數可以省去二進制寫入。

整個數據庫的刪除:

r.fushall()

批量刪除hash整體的大字典:

r.delete(*r.keys('^test'))   #表示刪除以test開頭的hash大字典。
r.delete(key1,key2)#表示刪除key1字典和key2字典

整個hash字典刪除:

r.delete(dict_name)

批量刪除具體某個hash字典的多個鍵:

r.hdel(dict_name,key1)

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。

推薦閱讀: