首页 > 解决方案 > redisTemplate 与 stringRedisTemplate!为什么 redisTemplate 设置命令不起作用?

问题描述

最近一直在用spring-boot-starter-data-redis;

我使用 spring-boot-version:2.3.8.RELEASE;

应用程序.yml

spring:
  redis:
    cluster:
      nodes:
        - 10.253.48.212:6379
        - 10.253.48.212:6380
        - 10.253.48.213:6379
        - 10.253.48.213:6380
        - 10.253.48.214:6379
        - 10.253.48.214:6380

我按照文章设置了Redis-Cluster; https://redis.io/topics/cluster-tutorial

设置过程也记录在additor中;虽然注释是中文的;

我按照文章spring-data-redis来使用Redis-Client;

我根据 [10.6. 通过 RedisTemplate 处理对象];

但是redisTemplate和stringRedisTemplate有问题;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {RedisApp.class})
public class RedisTest {

    @Resource(name="stringRedisTemplate")
    private ValueOperations<String, String> stringValueOperations;

    @Resource(name="redisTemplate")
    private ValueOperations<String, String> valueOperations;

    @Test
    public void test() {
        stringValueOperations.set("name", "yufr-bigName");
        valueOperations.set("name", "yufr");
        System.out.println(stringValueOperations.get("name"));
        System.out.println(valueOperations.get("name"));
    }

}

产生想法控制台:

yufr-bigName
yufr

导致redis-cluster-server:

10.253.48.214:6379> get name
"yufr-bigName"

为什么 redisTemplate 设置命令不起作用?

标签: spring-data-redis

解决方案


RedisSerializer 将键“名称”序列化为其他键,因此 redisTemplate 似乎不起作用;

关键代码是RedisSerializer;

    byte[] rawKey(Object key) {

        Assert.notNull(key, "non null key required");

        if (keySerializer() == null && key instanceof byte[]) {
            return (byte[]) key;
        }

        return keySerializer().serialize(key);
    }
    byte[] rawValue(Object value) {

        if (valueSerializer() == null && value instanceof byte[]) {
            return (byte[]) value;
        }

        return valueSerializer().serialize(value);
    }

defaultSerializer 是 JdkSerializationRedisSerializer

class RedisTemplate ... {

    ...

    public void afterPropertiesSet() {

        super.afterPropertiesSet();

        boolean defaultUsed = false;

        if (defaultSerializer == null) {

            defaultSerializer = new JdkSerializationRedisSerializer(
                    classLoader != null ? classLoader : this.getClass().getClassLoader());
        }

        if (enableDefaultSerializer) {

            if (keySerializer == null) {
                keySerializer = defaultSerializer;
                defaultUsed = true;
            }
            if (valueSerializer == null) {
                valueSerializer = defaultSerializer;
                defaultUsed = true;
            }

            ...

        }
    }
}

最终的序列化器是 org.springframework.core.serializer.DefaultSerializer

    public void serialize(Object object, OutputStream outputStream) throws IOException {
        if (!(object instanceof Serializable)) {
            throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +
                    "but received an object of type [" + object.getClass().getName() + "]");
        }
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(object);
        objectOutputStream.flush();
    }

所以字符串键“name”将由objectOutputStream处理;

    @Test
    public void serialize() {
        ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(out)) {
            objectOutputStream.writeObject("name");
            objectOutputStream.flush();
        } catch (IOException ioException) {
            
        }
        
        // �� t name
        System.out.println(new String(out.toByteArray()));
    }

这样 valueOperations.set("name", "yufr"); 不工作!


推荐阅读