Search code examples
spring-data-redis

redisTemplate vs stringRedisTemplate! why redisTemplate set-command does not work?


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?


Solution

  • 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!