Spring Boot+Hibernate集成Redisson时Redis请求量过高求助
问题:低请求量下Redis操作量异常飙升(250 RPS对应8万次/秒Redis操作)
技术栈与配置信息
应用基于Spring Boot开发,采用Hibernate作为持久层框架,Redis作为缓存,通过Redisson实现缓存集成。
Spring Redis缓存配置
@Bean public CacheManager cacheManager(RedissonClient redissonClient) { return new RedissonSpringCacheManager(redissonClient) { @Override public Cache getCache(String cacheName) { Cache cache = super.getCache(cacheName); return new RedisCacheWrapper(cache); } @Override protected CacheConfig createDefaultConfig() { CacheConfig cacheConfig = new CacheConfig(ttl, maxIdleTime); cacheConfig.setMaxSize(maxSize); return cacheConfig; } }; }
Hibernate实体缓存配置
@Cache(region = HIBERNATE_MY_REGION, usage = CacheConcurrencyStrategy.READ_WRITE) public class MyEntity{ ... }
依赖配置
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson-hibernate-53</artifactId> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> </dependency>
本地测试Redis性能截图

目前已将Redis切换为集群模式并添加从节点缓解压力,需定位问题根源并给出优化方案。
可能的问题根源
- Hibernate二级缓存细粒度操作:
READ_WRITE并发策略下,Hibernate可能对实体的每个属性或关联对象执行单独缓存操作,而非整体缓存实体。若实体存在多关联关系,会触发大量Redis请求。 - Redisson缓存配置不合理:
maxSize设置过小导致频繁缓存淘汰,引发大量删除、写入操作;TTL/MaxIdleTime过短导致缓存命中率极低,每次请求都需查询DB后写入Redis。 - 缓存穿透/批量查询无优化:大量请求数据不在缓存中,穿透到DB后写入Redis;批量查询场景未做批量缓存操作,单个请求触发多次Redis交互。
- 自定义RedisCacheWrapper冗余操作:
RedisCacheWrapper可能在get/put流程中新增了不必要的Redis交互(如额外exists检查、日志相关操作)。 - Hibernate缓存区域配置失效:多实体共用同一缓存区域或配置未生效,导致缓存无法复用,重复写入相同数据。
优化方案
调整Hibernate缓存策略
- 若业务允许最终一致性,改用
CacheConcurrencyStrategy.NONSTRICT_READ_WRITE,减少锁相关的Redis操作;确认READ_WRITE锁机制是否必要,排查Redisson实现是否存在过度锁交互。 - 对实体关联对象(
@OneToMany/@ManyToOne等)显式配置缓存,避免加载实体时单独查询关联数据触发缓存操作;或在Service层使用@Cacheable做粗粒度缓存,替代部分Hibernate二级缓存的细粒度操作。
优化Redisson缓存配置
- 增大
maxSize避免频繁缓存淘汰,根据业务访问模式调整TTL和MaxIdleTime,提升缓存命中率。 - 启用Redisson本地缓存,对热点数据在应用本地做一级缓存,减少远程Redis调用:
@Override protected CacheConfig createDefaultConfig() { CacheConfig cacheConfig = new CacheConfig(ttl, maxIdleTime); cacheConfig.setMaxSize(maxSize); // 配置本地缓存 LocalCacheConfig localCacheConfig = new LocalCacheConfig(); localCacheConfig.setTTL(10000); // 本地缓存有效期(毫秒) localCacheConfig.setMaxSize(1000); // 本地缓存最大容量 cacheConfig.setLocalCacheConfig(localCacheConfig); return cacheConfig; }
解决缓存穿透与批量查询问题
- 对不存在的ID请求添加空值缓存(设置较短TTL),避免频繁穿透到DB后写入Redis。
- 针对批量查询场景实现批量缓存操作,一次性查询多个ID并批量写入缓存,减少Redis交互次数。
排查自定义RedisCacheWrapper
- 审计
RedisCacheWrapper代码,移除不必要的Redis操作(如额外的exists、get请求),确保仅在必要时与Redis交互。
监控与调优
- 通过RedisInsight分析高频Redis命令类型(如是否大量HSET/HGET、DEL),定位操作来源。
- 开启Hibernate缓存统计(
hibernate.generate_statistics=true),分析缓存命中率、操作次数,确认是否由Hibernate二级缓存引发高频Redis调用。
内容的提问来源于stack exchange,提问作者Dmitry Shabalin
相关产品推荐
相关产品推荐

