共80行

redis key 问题

2026-07-14 15:55:18

redis key 问题

  LoginUserVO loginVO = new LoginUserVO(uid, token);
  // 刷新缓存
  String key = this.fixGetloginCacheKey(uid);
  redisUtil.save(key, JSON.toJSONString(loginVO), 1, TimeUnit.DAYS);
  1. 假如uid= 3 ,那么key存到redis里面却变成了 "\xac\xed\x00\x05t\x00\x1cPARKING_INVOICE_USER_LOGIN_3";
  2. value 变成了Binary格式

Qoder CN回答

这是经典的 Redis 序列化问题。\xac\xed\x00\x05 是 Java 原生序列化的魔术数字,说明 RedisTemplate 使用的是 JDK 默认序列化器,而不是字符串序列化器。

让我确认下项目中是否有 Redis 的序列化配置。

找到原因了。项目中没有自定义 RedisTemplate 的序列化器配置,Spring Boot 默认使用的是 JdkSerializationRedisSerializer,这就是问题根源。

原因分析

  1. Key 变成 \xac\xed\x00\x05t\x00\x1cPARKING_INVOICE_USER_LOGIN_3\xac\xed\x00\x05 是 Java 原生序列化的魔术数字(magic number),说明 key 也被 JDK 序列化了。正常情况下 key 应该用 StringRedisSerializer,直接存为可读字符串。

  2. Value 变成 Binary 格式:同理,value 的序列化器也是 JdkSerializationRedisSerializer,所以 JSON.toJSONString(loginVO) 这个字符串被再次 JDK 序列化,存进去就变成了二进制。

解决方案

infrastructure/config/ 下新建一个 Redis 配置类,自定义 RedisTemplate 的序列化器:

package com.dpb.tckp.infrastructure.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jsonSerializer.setObjectMapper(om);

        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);
        template.setValueSerializer(jsonSerializer);
        template.setHashValueSerializer(jsonSerializer);
        template.afterPropertiesSet();

        return template;
    }
}

配置后效果:

⚠️ 注意:修改序列化方式后,Redis 中已有的旧数据(JDK 序列化格式的)将无法被正确反序列化,需要清除旧缓存或重新写入。