RedisTemplate的RedisSerializer(序列化)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: RedisTemplate的RedisSerializer(序列化)

场景一

在使用 increment 时发生报错

io.lettuce.core.RedisCommandExecutionException: ERR value is not an integer or out of range

如下:

int id = (Integer) redisTemplate.opsForValue().get("id");
redisTemplate.opsForValue().increment("id",5);

场景二

成功执行了如下代码

@Test
    void contextLoads() {
        redisTemplate.opsForValue().set("id",0);
    }

Redis中却没出现 id 的key,而出现了一串字符 ,就连 value 也不是 0

 

上面两种场景都是因为 RedisTemplate 的序列化

上面我们可以看到 redistTemplate 的 set 方法接收的是 Object对象

redisTemplate的功能就是接收任何类型的对象,然后底层通过JDK序列化器,将Java对象转化为Redis可以识别的字节


我们跟踪 redistTemplate 的 set方法,可以发现set底层调用了 DefaultValueOperations<K, V> 中的set方法如下:

public void set(K key, V value) {
        final byte[] rawValue = this.rawValue(value);
        this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
            protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
                connection.set(rawKey, rawValue);
                return null;
            }
        });
    }

我们发现,传入的value被 rawValue方法转换成 byte数组,继续跟踪 rawValue方法

byte[] rawValue(Object value) {
        return this.valueSerializer() == null && value instanceof byte[] ? (byte[])((byte[])value) : this.valueSerializer().serialize(value);
    }

我们发现调用了serialize方法,继续跟踪serialize方法,发现我们进到了JdkSerializationRedisSerializer 的 serialize 方法,如下:

public byte[] serialize(@Nullable Object object) {
        if (object == null) {
            return SerializationUtils.EMPTY_ARRAY;
        } else {
            try {
                return (byte[])this.serializer.convert(object);
            } catch (Exception var3) {
                throw new SerializationException("Cannot serialize", var3);
            }
        }
    }

不断深入跟踪上面的convert方法,最后来到了 DefaultSerializer 中的 serialize方法,我们看到底层用到了 ObjectOutputStream 将object对象转换为字节流写入Redis, 从而就达到了我们看到的效果

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

这种序列化方式有俩个弊端:

  • 可读性极差
  • 内存占用大

如何做到 写入 的跟 存入 的是一样的呢?

这只需要修改RedisTemplate的序列化方式,添加如下配置类

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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置Key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

重新运行

查看Redis

成功了,没毛病 ^ - ^

插入一个对象看看

import lombok.Data;
@Data
public class User {
    private String name;
    private Integer age;
}

还是没毛病 嘿嘿 ^ - ^

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
JSON NoSQL Java
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
这篇文章介绍了在Java中使用Redis客户端的几种方法,包括Jedis、SpringDataRedis和SpringBoot整合Redis的操作。文章详细解释了Jedis的基本使用步骤,Jedis连接池的创建和使用,以及在SpringBoot项目中如何配置和使用RedisTemplate和StringRedisTemplate。此外,还探讨了RedisTemplate序列化的两种实践方案,包括默认的JDK序列化和自定义的JSON序列化,以及StringRedisTemplate的使用,它要求键和值都必须是String类型。
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
|
4月前
RedisTemplate序列化的问题
RedisTemplate序列化的问题
40 1
|
6月前
|
存储 JSON NoSQL
[Redis]——RedisTemplate的两种序列化方式
[Redis]——RedisTemplate的两种序列化方式
330 0
|
存储 NoSQL Java
【Spring技术原理】分析探究RedisTemplate的序列化和反序列化+泛型机制
【Spring技术原理】分析探究RedisTemplate的序列化和反序列化+泛型机制
1065 0
|
缓存 NoSQL Java
SpringBoot自定义redisTemplate的key和value的序列化方式
SpringBoot自定义redisTemplate的key和value的序列化方式
163 0
|
XML JSON NoSQL
Redis - RedisTemplate及4种序列化方式深入解读
Redis - RedisTemplate及4种序列化方式深入解读
1432 0
|
消息中间件 JSON 缓存
RedisTemplate&amp 序列化机制|学习笔记
快速学习 RedisTemplate&amp 序列化机制
154 0
|
存储 JSON NoSQL
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(中)
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(中)
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(中)
|
存储 JSON 缓存
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(上)
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(上)
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(上)
|
NoSQL Java fastjson
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(下)
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(下)