spring-boot-starter-data-redis 不提供开箱即用的数据压缩能力,压缩必须在 RedisTemplate 的 valueSerializer 中手动实现,如通过 GzipJackson2JsonRedisSerializer 在序列化时压缩 JSON 字节流,并兼顾小数据跳过、旧数据兼容与线程安全。

spring-boot-starter-data-redis 本身**不提供开箱即用的数据压缩能力**。所谓“配置 spring.redis.jedis.pool.config.compress=true”是常见误解——该配置项根本不存在于 Spring Boot 官方属性中,Jedis 连接池也**不负责序列化或压缩逻辑**。
真正可控的压缩点,在于你如何序列化数据再写入 Redis。压缩必须发生在序列化环节,而不是连接池或网络传输层。
RedisTemplate 的 value 序列化器才是压缩入口
默认的 RedisTemplate 使用 JdkSerializationRedisSerializer,它不支持压缩,且生成的二进制不可读、跨语言困难。要压缩,就得替换掉它的 valueSerializer。
典型做法是:在序列化前对 JSON 字节流做 GZIP 压缩,反序列化时再解压。
- 用
Jackson2JsonRedisSerializer将对象转为byte[] - 用
GZIPOutputStream包裹输出流,压缩字节 - 将压缩后的
byte[]作为最终 value 存入 Redis - 读取时先解压,再用 Jackson 反序列化
示例关键代码片段:
public class GzipJackson2JsonRedisSerializer<T> extends Jackson2JsonRedisSerializer<T> {
public GzipJackson2JsonRedisSerializer(Class<T> clazz) {
super(clazz);
}
@Override
public byte[] serialize(T t) throws SerializationException {
byte[] json = super.serialize(t);
if (json == null || json.length <= 1024) return json; // 小数据不压
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gos = new GZIPOutputStream(baos)) {
gos.write(json);
gos.finish();
return baos.toByteArray();
} catch (IOException e) {
throw new SerializationException("Cannot compress", e);
}
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null) return null;
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
try (GZIPInputStream gis = new GZIPInputStream(bais)) {
return super.deserialize(StreamUtils.copyToByteArray(gis));
}
} catch (IOException e) {
// 非 gzip 数据(如旧缓存),fallback 到原逻辑
return super.deserialize(bytes);
}
}
}
为什么不能依赖 Lettuce 或 Jedis 自动压缩?
Lettuce 和 Jedis 是客户端驱动,只管发命令、收响应,**不干涉你传进去的 value 字节内容**。它们不会主动压缩/解压,也不识别你存的是不是 gzip 流。
常见误判来源:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 把 Redis 服务端的
rdbcompression yes(RDB 文件压缩)当成 value 压缩 —— 这仅影响磁盘快照,不影响内存中 key-value 的大小 - 混淆了连接池配置(如
max-active)和序列化行为 - 误信某些过时博客里伪造的
spring.redis.***.compress属性
压缩带来的实际影响与取舍
压缩确实能显著减小 value 体积(实测 JSON 对象通常压缩率 70%~85%),但代价明确:
- CPU 开销上升:每次读写都多一次 gzip 压缩/解压,QPS 高时可能成为瓶颈
- 调试变困难:Redis CLI 或 GUI 工具看到的是乱码二进制,无法直接 inspect 内容
- 兼容性风险:如果后续换客户端(比如用 Python 的 redis-py),必须同步实现相同压缩逻辑,否则读失败
- 小数据负优化:小于 1KB 的字符串压缩后反而可能略大(gzip header 开销)
建议加一个 size 阈值判断(如示例中 <= 1024 跳过压缩),避免得不偿失。
CacheManager 场景下怎么加压缩?
如果你用 @Cacheable 注解走 RedisCacheManager,就不能直接改 RedisTemplate,而要替换 RedisCacheConfiguration 中的 value 序列化器:
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(
new GzipJackson2JsonRedisSerializer<>(Object.class)
));
注意:这个序列化器必须线程安全(无状态),且需处理好空值、异常 fallback(比如旧未压缩数据要能兼容读取)。
真正决定是否压缩的,不是配置开关,而是你亲手写的那个serialize() 方法。所有压缩逻辑都在这里,别指望框架替你做。

















