0
votes

Recently I have been using spring-boot-starter-data-redis;

I use spring-boot-version:2.3.8.RELEASE;

application.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

I set up Redis-Cluster according to the article; https://redis.io/topics/cluster-tutorial

The setup process was also recorded in additor;although the notes were in Chinese;

I follow the article spring-data-redis to use Redis-Client;

I wrote the code based on the [10.6. Working with Objects through RedisTemplate];

But there was a problem with redisTemplate and 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"));
    }

}

result in idea-console:

yufr-bigName
yufr

result in redis-cluster-server:

10.253.48.214:6379> get name
"yufr-bigName"

why redisTemplate set-command does not work?

1

1 Answers

0
votes

RedisSerializer serialize the key "name" to other key, so redisTemplate doesn't seem to work;

The key code is 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);
    }

the defaultSerializer is 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;
            }

            ...

        }
    }
}

the final serializer is 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();
    }

so the string key "name" will be processed by 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()));
    }

so that valueOperations.set("name", "yufr"); does not work!