現象:
使用Java Redis客戶端將資料存放到Redis後,使用redisTemplate卻不出來
原因:
Java Redis客戶端在將資料存放在Redis時,會對Key,Value,Field進行編碼。從Redis中取資料時,如果Key、Field的編碼和存放時不一樣,就會取不出來。
就像中文亂碼一樣,同樣的中文字串,存放時編碼格式不對,就不能被識別。
問題覆盤及分析過程:
(1)使用下面程式碼將資料放到Redis中
stringRedisTemplate.opsForHash().put("CATALOG_DEV","KEY_INDEX_CATALOG",JsonUtil.list2json(list));
(2)使用方式1,可以hget到的value和存放時的一致:
stringRedisTemplate.opsForHash().get("CATALOG_DEV","KEY_INDEX_CATALOG")
(3)使用方式2,hget到的value是nulll:
redisTemplate.opsForHash().get("CATALOG_DEV","KEY_INDEX_CATALOG")
使用wireshark抓包:
方式1時,HGET命令傳送到Redis伺服器的指令:
方式2時,HGET命令傳送到Redis伺服器的指令:
可見,雖然程式碼中,Redis的Java客戶端傳送的key和field都是相同和字串,但Redis接受到的Field卻是不同的。
看看Redis伺服器上存放的Field是什麼樣的:
看一個使用redisTemplate客戶端存放的資料:
對比看下方式1存放到Redsi伺服器上的資料
為什麼有這個差異呢?來看看Spring容器中的stringRedisTemplate 和 redisTemplate例項有什麼區別:
RedisTemplate的例項化程式碼如下:
@Bean @SuppressWarnings({"rawtypes", "unchecked"}) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisSerializer<String> stringSerializer = new StringRedisSerializer(); RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 設定value的序列化採用Jackson2JsonRedisSerializer template.setValueSerializer(jackson2JsonRedisSerializer); // 設定key的序列化採用StringRedisSerializer template.setKeySerializer(stringSerializer); // template.setHashKeySerializer(stringSerializer); // template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; }
HashKeySerializer、HashValueSerializer沒有指定,應該會走預設,如下圖所示:
StringRedisTemplate的例項化程式碼如下:
@Bean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; }
可以看到,HashKeySerializer、HashValueSerializer都使用了StringRedisSerializer,與上面的情況一致。O了
擴充套件:
WireShark抓包利器:
https://github.com/jzwinck/redis-wireshark
連結:https://pan.baidu.com/s/1M9tXDN54FODU7NftkLfwKQ
提取碼:kzhc
複製這段內容後開啟百度網盤手機App,操作更方便哦
檢視WireShark外掛配置目錄及已經配置外掛的資訊:
外掛copy到目錄:幫助--》關於--》資料夾--》Personal configuration
已經安裝的外掛列表: