使用WireShark分析使用RedisTemplate取不到值的問題



現象:
使用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


已經安裝的插件列表:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM