Redisson 自定义序列化 Codec 实战指南:原理、实现与踩坑记录

Redisson 自定义序列化 Codec 实战指南:原理、实现与踩坑记录

📚 背景介绍:为什么要自定义 Codec?

Redisson 默认支持多种序列化方式(如 JsonJacksonCodec, FstCodec, KryoCodec 等),但在实际项目中可能遇到如下问题:

  • 默认的序列化器无法满足精度、兼容性或安全性要求
  • 要与其他服务(如 Python/Golang)兼容通信格式
  • 想要替换掉过大的 Jackson,换成轻量的 JSON 序列化方式
  • 需要对某些字段做脱敏或加密处理

🧩 Codec 接口原理简析

java 复制代码
public interface Codec extends Serializable {
    Decoder<Object> getValueDecoder();
    Encoder getValueEncoder();
    Decoder<Object> getMapValueDecoder();
    Encoder getMapValueEncoder();
    Decoder<Object> getMapKeyDecoder();
    Encoder getMapKeyEncoder();
}

✍️ 实战演练:自定义 FastJson Codec

java 复制代码
public class FastJsonCodec implements Codec {
    private final Charset charset = StandardCharsets.UTF_8;

    @Override public Decoder<Object> getValueDecoder() { return this::decode; }
    @Override public Encoder getValueEncoder() { return this::encode; }
    @Override public Decoder<Object> getMapValueDecoder() { return getValueDecoder(); }
    @Override public Encoder getMapValueEncoder() { return getValueEncoder(); }
    @Override public Decoder<Object> getMapKeyDecoder() { return getValueDecoder(); }
    @Override public Encoder getMapKeyEncoder() { return getValueEncoder(); }

    private byte[] encode(Object in) throws IOException {
        if (in == null) return new byte[0];
        String json = JSON.toJSONString(in);
        return json.getBytes(charset);
    }

    private Object decode(ByteBuffer buf, ClassLoader classLoader) throws IOException {
        if (!buf.hasRemaining()) return null;
        byte[] bytes = new byte[buf.remaining()];
        buf.get(bytes);
        return JSON.parse(new String(bytes, charset));
    }
}

🔧 配置与使用

java 复制代码
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
config.setCodec(new FastJsonCodec());
RedissonClient redisson = Redisson.create(config);

🧪 测试验证

java 复制代码
@Test
public void testFastJsonCodec() {
    RMap<String, MyDTO> map = redisson.getMap("myMap");
    map.put("key", new MyDTO("test", 123));
    MyDTO value = map.get("key");

    assertEquals("test", value.getName());
    assertEquals(123, value.getValue());
}

⚠️ 踩坑与注意事项

  1. 类型信息丢失:使用 WriteClassName 写入类型,启用 autoType 支持(有安全风险)
  2. 编码一致性:统一使用 UTF-8 避免乱码
  3. 服务兼容性:跨语言建议使用 JSON 或 Protobuf
相关推荐
短剑重铸之日1 小时前
《SpringCloud实用版》 Seata 分布式事务实战:AT / TCC / Saga /XA
后端·spring·spring cloud·seata·分布式事务
FAFU_kyp1 小时前
RISC0_ZERO项目在macOs上生成链上证明避坑
开发语言·后端·学习·macos·rust
qq_12498707531 小时前
基于springboot的会议室预订系统设计与实现(源码+论文+部署+安装)
java·vue.js·spring boot·后端·信息可视化·毕业设计·计算机毕业设计
女王大人万岁2 小时前
Go语言time库核心用法与实战避坑
服务器·开发语言·后端·golang
h7ml2 小时前
高并发场景下查券返利机器人的请求合并与缓存预热策略(Redis + Caffeine 实践)
数据库·redis·缓存
J_liaty2 小时前
Spring Boot + MinIO 文件上传工具类
java·spring boot·后端·minio
短剑重铸之日2 小时前
《SpringCloud实用版》Stream + RocketMQ 实现可靠消息 & 事务消息
后端·rocketmq·springcloud·消息中间件·事务消息
没有bug.的程序员2 小时前
Spring Boot 事务管理:@Transactional 失效场景、底层内幕与分布式补偿实战终极指南
java·spring boot·分布式·后端·transactional·失效场景·底层内幕
LuminescenceJ3 小时前
GoEdge 开源CDN 架构设计与工作原理分析
分布式·后端·网络协议·网络安全·rpc·开源·信息与通信
Tony Bai3 小时前
【分布式系统】11 理论的试金石:用 Go 从零实现一个迷你 Raft 共识
开发语言·后端·golang