Redis的序列化配置

Redis序列化配置

一 源码概述

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
    private boolean enableTransactionSupport = false;
    private boolean exposeConnection = false;
    private boolean initialized = false;
    private boolean enableDefaultSerializer = true;
    @Nullable
    private RedisSerializer<?> defaultSerializer;
    @Nullable
    private ClassLoader classLoader;
    @Nullable
    private RedisSerializer keySerializer = null;
    @Nullable
    private RedisSerializer valueSerializer = null;
    @Nullable
    private RedisSerializer hashKeySerializer = null;
    @Nullable
    private RedisSerializer hashValueSerializer = null;
    private RedisSerializer<String> stringSerializer = RedisSerializer.string();
    @Nullable
    private ScriptExecutor<K> scriptExecutor;
    private final ValueOperations<K, V> valueOps = new DefaultValueOperations(this);
    private final ListOperations<K, V> listOps = new DefaultListOperations(this);
    private final SetOperations<K, V> setOps = new DefaultSetOperations(this);
    private final StreamOperations<K, ?, ?> streamOps = new DefaultStreamOperations(this, new ObjectHashMapper());
    private final ZSetOperations<K, V> zSetOps = new DefaultZSetOperations(this);
    private final GeoOperations<K, V> geoOps = new DefaultGeoOperations(this);
    private final HyperLogLogOperations<K, V> hllOps = new DefaultHyperLogLogOperations(this);
    private final ClusterOperations<K, V> clusterOps = new DefaultClusterOperations(this);

    public RedisTemplate() {
    }

    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        boolean defaultUsed = false;
        if (this.defaultSerializer == null) {
            this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
        }

        if (this.enableDefaultSerializer) {
            if (this.keySerializer == null) {
                this.keySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

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

            if (this.hashKeySerializer == null) {
                this.hashKeySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashValueSerializer == null) {
                this.hashValueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }
        }

        if (this.enableDefaultSerializer && defaultUsed) {
            Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
        }

        if (this.scriptExecutor == null) {
            this.scriptExecutor = new DefaultScriptExecutor(this);
        }

        this.initialized = true;
    }
}

根据源码可知,当没有配置序列化策略的时候,采用的是默认的序列化策略,即

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

默认的序列化方式使得我们在Redis客户端查看是不是很好查看。

二 自定义序列化策略

        key采用字符串系列化策略,而value则采用fastJson序列化策略。

        自定义FastJson序列化配置

public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
    private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private Class<T> clazz;
    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (null == t) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (null == bytes || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        //禁用关键字检测
        return JSON.parseObject(str, clazz, Feature.DisableSpecialKeyDetect);
    }
}

         redis序列化配置

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        //使用fastjson序列化
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
        // value值的序列化采用fastJsonRedisSerializer
        template.setValueSerializer(fastJsonRedisSerializer);
        template.setHashValueSerializer(fastJsonRedisSerializer);
        // key的序列化采用StringRedisSerializer
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean(StringRedisTemplate.class)
    public StringRedisTemplate stringRedisTemplate(
            RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

}

序列化配置之后,key和value分别是String和json格式,易于查看:

 

### Redis 中除 String 类型外的序列化策略 #### Hash 数据类型的序列化方式 对于 Hash 类型,在内存中的表示形式为压缩列表或哈希表。当其被持久化到磁盘时,会转换成一种特定格式保存。具体来说,每个字段名和对应的值都会作为独立的对象进行编码处理[^2]。 ```python # Python伪代码展示如何模拟Hash对象的简单序列化过程 class SimpleHashSerializer: @staticmethod def serialize(hash_data): serialized_items = [] for field, value in hash_data.items(): # 将field和value分别视为单独实体来序列化 serialized_field = f"FIELD:{field}" serialized_value = f"VALUE:{value}" serialized_items.append(serialized_field) serialized_items.append(serialized_value) return "\n".join(serialized_items) hash_example = {"name": "Alice", "age": 30} print(SimpleHashSerializer.serialize(hash_example)) ``` #### List 数据类型的序列化方法 List 类型内部实现上可以是双向链表或是压缩列表。在RDB文件中存储时,则是以一系列节点的形式存在,其中包含了指向前后元素的信息以及自身的值。为了节省空间并提高效率,如果连续多个整数会被优化打包在一起。 ```python # Python伪代码展示简单的List序列化逻辑 def simple_list_serialize(lst): result = ["TYPE LIST"] prev_int = None int_count = 0 for item in lst: if isinstance(item, int) and (prev_int is not None or int_count > 0): if item == prev_int + 1: int_count += 1 continue else: if int_count >= 3: # 当有至少三个连续整数才会做特别处理 result.append(f"INTS {int_count} FROM {item-int_count}") int_count = 0 result.append(str(item)) prev_int = item if isinstance(item, int) else None if int_count >= 3: result.append(f"INTS {int_count} FROM {lst[-1]-int_count+1}") return "\n".join(result) example_list = ['a', 'b', 1, 2, 3, 4, 'c'] print(simple_list_serialize(example_list)) ``` #### Set 和 ZSet 的序列化机制 Sets 使用的是字典结构(即hashtable),这意味着它们能够快速完成成员测试操作,并且保证所有条目唯一。而Sorted Sets不仅具备上述特性还额外维护了一个分数属性用于排序目的;因此,在实际应用过程中,sorted sets会在原有基础上附加一个double精度浮点数用来记录权重信息。这两种类型最终也会按照一定规则转化为适合长期储存的形式写入AOF日志或者创建快照[RDB][^3]。 ```python # Python伪代码描述Set/ZSet简化版序列化流程 from collections import defaultdict class SimplifiedSetZsetSerializer: @staticmethod def serialize_set(set_data): lines = ["TYPE SET"] + [str(member) for member in set_data] return '\n'.join(lines) @staticmethod def serialize_zset(zset_data): # zset_data should be a dict mapping members to scores sorted_members = sorted(zset_data.items(), key=lambda kv: (-kv[1], kv[0])) lines = ["TYPE ZSET"] + [ f"{member}:{score}" for member, score in sorted_members ] return '\n'.join(lines) sample_set = {'apple', 'banana'} sample_zset = {'orange': 9.5, 'grape': 7.8} print(SimplifiedSetZsetSerializer.serialize_set(sample_set)) print("\n") print(SimplifiedSetZsetSerializer.serialize_zset(sample_zset)) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值