当前位置: 代码网 > it编程>数据库>Redis > Redis键值对序列化指南

Redis键值对序列化指南

2026年09月07日 Redis 我要评论
看看序列化是怎么来的先从<string, string>开始redistemplate.opsforvalue().set("name", "alice");string value =

看看序列化是怎么来的

先从<string, string>开始

redistemplate.opsforvalue().set("name", "alice");
string value = redistemplate.opsforvalue().get("name");

从 java 代码层面看,这很好理解:

  • set("name", "alice"):把 alice 存到 key 为 name 的位置
  • get("name"):根据 key name 把值取出来

对应到 redis 命令层面,可以理解为:

set name alice
get name

因为这里的 key 和 value 都是字符串,所以这个过程非常直观。

也正因为如此,<string, string> 是理解 redistemplate 数据转换的最好起点。

再看<string, object>这个层面

如果现在 value 不再是字符串,而是一个对象,例如:

user user = new user(1l, "alice", 18);
redistemplate.opsforvalue().set("user:1", user);

这时候就不能再简单理解成:

set user:1 user对象

因为 redis 命令层面并不认识 java 的 user 对象。

也就是说,对象不能直接原样放进 redis,必须先转换成 redis 能接受的形式。

最容易想到的一种方式,就是先把对象转成字符串,例如 json 字符串:

string userstring = jsonobject.tojsonstring(user);
redistemplate.opsforvalue().set("user:1", userstring);

这样到了 redis 命令层面,就更容易理解成:

set user:1 {"id":1,"name":"alice","age":18}

所以,这一步的核心认识是:

  • string 类型之所以简单,是因为它本身就很接近 redis 命令里的值。
  • object 类型之所以复杂,是因为它必须先转换成某种可表示的形式。

为什么会引出“序列化”

当我们从 **<string, string>** 进入 **<string, object>** 后,就会自然遇到这个问题:

  • 字符串可以直接放,对象不能直接放,那对象要怎么变成 redis 能存的内容?

这时候就需要一个“转换过程”,这个过程本质上就是序列化,你可以直接这样理解:

  • 序列化,就是把 java 对象转换成 redis 能接收、能存储的形式。

反过来,取值时再把它还原成 java 对象,这就是反序列化。

一开始可以手动做序列化

最原始、最容易理解的做法,就是自己手动转:

string userstring = jsonobject.tojsonstring(user);
redistemplate.opsforvalue().set("user:1", userstring);

取出来的时候再手动转回来:

string userstring = redistemplate.opsforvalue().get("user:1");
user user = jsonobject.parseobject(userstring, user.class);

这种做法的优点是:

  • 容易理解
  • 逻辑清晰
  • 很适合初学阶段建立概念

但问题也很明显:

  • 每次 set 都要手动 tojsonstring
  • 每次 get 都要手动 parseobject
  • 重复代码很多
  • 业务代码里混入了太多转换逻辑

所以会进一步封装 redisutils

为了避免每次都手动写转换代码,就会想到封装工具类,例如:

public void set(string key, object obj) {
    string str = jsonobject.tojsonstring(obj);
    redistemplate.opsforvalue().set(key, str);
}

这样做的意义是:把“对象转字符串”的重复逻辑,从业务代码中抽离出去。

业务层以后就不用反复写:

jsonobject.tojsonstring(obj)

而是直接调用工具方法。

不过这里要注意一点:这仍然是你自己在 java 代码里手动做转换,只不过把它封装起来了。

再后来,就会把序列化规则直接交给 redistemplate

现在抛弃封装 redisutils 方式,直接在 redistemplate 的配置类里,给 key 和 value 设置序列化方式。

这样之后,代码就可以直接写成:

redistemplate.opsforvalue().set("user:1", user);

这时候并不是 redis 直接认识了 user 对象,而是:

  • 你传进去的是 user
  • redistemplate 会按照你配置好的序列化器,先把它转换成指定格式
  • 然后再执行 redis 操作

所以更准确的理解应该是:不是 redis 能直接存 java 对象了,而是 redistemplate 先帮我们把对象转换好了。

这就是为什么后面我们可以直接写:

redistemplate.opsforvalue().set("user:1", user);

而不用每次都手动写 jsonobject.tojsonstring(user)

不同场景会选不同的序列化方式

  1. jdk 序列化

:::color3
jdk 序列化通常是 spring 体系里常见的默认方案之一。

它的特点是可以直接处理 java 对象,但在 redis 中存出来的结果通常不可读,看起来像乱码。

更准确地说,不是它“出了乱码”,而是:jdk 序列化后的内容本来就不是给人直接阅读的文本。

所以你在 redis 可视化工具里看时,会觉得它不可读。

  1. json 序列化

:::color3

json 序列化会把对象转成 json 文本再存入 redis。

它的好处是:

  • 可读性强
  • 调试方便
  • 很适合大多数业务场景

所以很多项目里,key 用字符串序列化,value 用 json 序列化,是很常见的搭配。

  1. 自定义序列化

:::color3

如果现成方案不能满足需求,也可以自己定义序列化规则。

也就是说,你自己决定:

  • 对象怎么转成可存储内容
  • 取出来时又怎么转回对象

这种方式灵活,但实现和维护成本更高。

代码示例

value 采用 jdk 序列化

package com.example.demo.config;

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.jdkserializationredisserializer;
import org.springframework.data.redis.serializer.stringredisserializer;

@configuration
public class redisjdkconfig {

    @bean
    public redistemplate<string, object> jdkredistemplate(redisconnectionfactory connectionfactory) {
        redistemplate<string, object> redistemplate = new redistemplate<>();
        redistemplate.setconnectionfactory(connectionfactory);

        stringredisserializer keyserializer = new stringredisserializer();
        jdkserializationredisserializer valueserializer = new jdkserializationredisserializer();

        redistemplate.setkeyserializer(keyserializer);
        redistemplate.sethashkeyserializer(keyserializer);

        redistemplate.setvalueserializer(valueserializer);
        redistemplate.sethashvalueserializer(valueserializer);

        redistemplate.afterpropertiesset();
        return redistemplate;
    }
}

value 采用 json 序列化

package com.example.demo.config;

import com.fasterxml.jackson.annotation.jsontypeinfo;
import com.fasterxml.jackson.databind.objectmapper;
import com.fasterxml.jackson.databind.jsontype.basicpolymorphictypevalidator;
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.stringredisserializer;

@configuration
public class redisjsonconfig {

    @bean
    public redistemplate<string, object> jsonredistemplate(redisconnectionfactory connectionfactory) {
        redistemplate<string, object> redistemplate = new redistemplate<>();
        redistemplate.setconnectionfactory(connectionfactory);

        stringredisserializer keyserializer = new stringredisserializer();

        objectmapper objectmapper = new objectmapper();
        objectmapper.activatedefaulttyping(
            basicpolymorphictypevalidator.builder()
            .allowifsubtype(object.class)
            .build(),
            objectmapper.defaulttyping.non_final,
            jsontypeinfo.as.property
        );

        genericjackson2jsonredisserializer valueserializer =
        new genericjackson2jsonredisserializer(objectmapper);

        redistemplate.setkeyserializer(keyserializer);
        redistemplate.sethashkeyserializer(keyserializer);

        redistemplate.setvalueserializer(valueserializer);
        redistemplate.sethashvalueserializer(valueserializer);

        redistemplate.afterpropertiesset();
        return redistemplate;
    }
}

value 采用自定义序列化的代码示例

第一步:自定义 user类

package com.example.demo.model;

import java.io.serializable;

@data
@noargsconstructor
@allargsconstructor
public class user implements serializable {
    private long id;
    private string name;
    private integer age;
}

第二步:自定义序列化器

package com.example.demo.serializer;

import com.example.demo.model.user;
import org.springframework.data.redis.serializer.redisserializer;
import org.springframework.data.redis.serializer.serializationexception;

import java.nio.charset.standardcharsets;

public class userredisserializer implements redisserializer<user> {

    @override
    public byte[] serialize(user user) throws serializationexception {
        if (user == null) {
            return new byte[0];
        }
        string value = user.getid() + "," + user.getname() + "," + user.getage();
        return value.getbytes(standardcharsets.utf_8);
    }

    @override
    public user deserialize(byte[] bytes) throws serializationexception {
        if (bytes == null || bytes.length == 0) {
            return null;
        }

        string value = new string(bytes, standardcharsets.utf_8);
        string[] arr = value.split(",");

        if (arr.length != 3) {
            throw new serializationexception("user 反序列化失败,数据格式不正确: " + value);
        }

        user user = new user();
        user.setid(long.parselong(arr[0]));
        user.setname(arr[1]);
        user.setage(integer.parseint(arr[2]));
        return user;
    }
}

第三步:配置 redistemplate

package com.example.demo.config;

import com.example.demo.model.user;
import com.example.demo.serializer.userredisserializer;
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.stringredisserializer;

@configuration
public class rediscustomconfig {

    @bean
    public redistemplate<string, user> customredistemplate(redisconnectionfactory connectionfactory) {
        redistemplate<string, user> redistemplate = new redistemplate<>();
        redistemplate.setconnectionfactory(connectionfactory);

        stringredisserializer keyserializer = new stringredisserializer();
        userredisserializer valueserializer = new userredisserializer();

        redistemplate.setkeyserializer(keyserializer);
        redistemplate.sethashkeyserializer(keyserializer);

        redistemplate.setvalueserializer(valueserializer);
        redistemplate.sethashvalueserializer(valueserializer);

        redistemplate.afterpropertiesset();
        return redistemplate;
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com