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
<h3>为什么不能依赖 Lettuce 或 Jedis 自动压缩?</h3>
<p>Lettuce 和 Jedis 是客户端驱动,只管发命令、收响应,**不干涉你传进去的 value 字节内容**。它们不会主动压缩/解压,也不识别你存的是不是 gzip 流。</p>
<p>常见误判来源:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill3464" title="Redis Skill - 高性能缓存管理"><img
src="https://img.php.cn/upload/skill/000/000/081/178960683454849.jpg" alt="Redis Skill - 高性能缓存管理" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill3464" title="Redis Skill - 高性能缓存管理" class="overflowclass">Redis Skill - 高性能缓存管理</a>
<p class="overflowclass">Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。</p>
</div>
<a rel="nofollow" href="/xiazai/skill3464" title="Redis Skill - 高性能缓存管理" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>把 Redis 服务端的 <code>rdbcompression yes</code>(RDB 文件压缩)当成 value 压缩 —— 这仅影响磁盘快照,不影响内存中 key-value 的大小</li>
<li>混淆了连接池配置(如 <code>max-active</code>)和序列化行为</li>
<li>误信某些过时博客里伪造的 <code>spring.redis.***.compress</code> 属性</li>
</ul>
<h3>压缩带来的实际影响与取舍</h3>
<p>压缩确实能显著减小 value 体积(实测 JSON 对象通常压缩率 70%~85%),但代价明确:</p>
<ul>
<li>CPU 开销上升:每次读写都多一次 gzip 压缩/解压,QPS 高时可能成为瓶颈</li>
<li>调试变困难:Redis CLI 或 GUI 工具看到的是乱码二进制,无法直接 inspect 内容</li>
<li>兼容性风险:如果后续换客户端(比如用 Python 的 <a style="color:#f60; text-decoration:underline;" title="redis" href="https://m.php.cn/zt/15737.html" target="_blank">redis</a>-py),必须同步实现相同压缩逻辑,否则读失败</li>
<li>小数据负优化:小于 1KB 的字符串压缩后反而可能略大(gzip header 开销)</li>
</ul>
<p>建议加一个 size 阈值判断(如示例中 <code> 跳过压缩),避免得不偿失。</code></p>
<h3>CacheManager 场景下怎么加压缩?</h3>
<p>如果你用 <code>@Cacheable</code> 注解走 <code>RedisCacheManager</code>,就不能直接改 <code>RedisTemplate</code>,而要替换 <code>RedisCacheConfiguration</code> 中的 value 序列化器:</p>
<pre class="brush:php;toolbar:false;">RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(
new GzipJackson2JsonRedisSerializer(Object.class)
));
注意:这个序列化器必须线程安全(无状态),且需处理好空值、异常 fallback(比如旧未压缩数据要能兼容读取)。
真正决定是否压缩的,不是配置开关,而是你亲手写的那个serialize() 方法。所有压缩逻辑都在这里,别指望框架替你做。










