現象:
使用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
已經安裝的插件列表:

