Java-Redis 缓存「从入门到黑科技」2026 版

一篇看懂:缓存模型 → 实战代码 → 高阶玩法 → 暗黑黑科技 所有示例基于 Spring Boot 3 & Redis 7,复制即可跑。

一、概念速览:4 种缓存模式一张图

模式 谁来写缓存 一致性 适用场景
Cache Aside 应用自己 中等 读多写少,最常用
Read Through Redis 插件 较好 读多,缓存层透明
Write Through 同步写 DB+缓存 写多,强一致
Write Behind 先写缓存,异步刷盘 最高吞吐 计数器、秒杀

二、Spring Boot 3 快速落地(Cache Aside)

1.依赖 & 配置

XML 复制代码
spring: 
  redis: 
    host: localhost 
    port: 6379 
  cache: 
    type: redis # 开启 Spring Cache 
    redis:  
      time-to-live: 3600s 
      key-prefix: demo 
      use-key-prefix: true

2.启动类加 @EnableCaching

3.业务代码(零侵入)

java 复制代码
@Service 
public class ProductService { 
  @Cacheable(value = "product", key = "#id") 
  public Product getProduct(Long id) { 
    return dao.selectById(id); // 缓存未命中才走 DB 
  } 
  @CacheEvict(value = "product", key = "#id") 
  public void updateProduct(Long id, Product p) { 
    dao.updateById(id, p); 
  } 
}

效果:第一次查 DB,后续 1h 内直接走 Redis;更新时自动失效。

三、进阶:手写 RedisTemplate 模板(细粒度控制)

java 复制代码
@Configuration 
public class RedisConfig { 
  @Bean 
  public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory f) {
    RedisTemplate<String, Object> t = new RedisTemplate<>(); 
    t.setConnectionFactory(f); 
    // 序列化 
    GenericJackson2JsonRedisSerializer json = new GenericJackson2JsonRedisSerializer();
    t.setKeySerializer(RedisSerializer.string()); 
    t.setValueSerializer(json); 
    t.setHashKeySerializer(RedisSerializer.string()); 
    t.setHashValueSerializer(json); 
    return t;    
  } 
}

工具类封装:

java 复制代码
@Component 
public class RedisUtil { 
  @Resource 
  private RedisTemplate<String, Object> redisTemplate; 
  public void set(String k, Object v, long seconds) { 
    redisTemplate.opsForValue().set(k, v, Duration.ofSeconds(seconds)); 
  } 
  public <T> T get(String k, Class<T> clazz) { 
    return (T) redisTemplate.opsForValue().get(k); 
  } 
  public boolean exists(String k) { 
    return Boolean.TRUE.equals(redisTemplate.hasKey(k)); 
  } 
}

使用:

java 复制代码
String key = "product:" + id; 
Product p = redisUtil.get(key, Product.class); 
if (p == null) { 
  p = dao.selectById(id); 
  redisUtil.set(key, p, 3600); 
}

四、高并发三板斧

  1. 分布式锁(防超卖)
java 复制代码
public boolean deductStock(Long id, int num) { 
  String lockKey = "lock:stock:" + id; 
  String uuid = Thread.currentThread().getId() + ":" + System.nanoTime(); 
  Boolean ok = redisTemplate.opsForValue() .setIfAbsent(lockKey, uuid, 10, TimeUnit.SECONDS); 
  if (!Boolean.TRUE.equals(ok)) return false; 
  try { 
    int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock:" + id)); 
    if (stock < num) return false; 
    redisTemplate.opsForValue().decrement("stock:" + id, num); 
    return true; 
   } finally { 
    // 用 Lua 保证"自己的锁自己解" 
    String script = "if redis.call('get',KEYS[1])==ARGV[1] then " + "return redis.call('del',KEYS[1]) else return 0 end"; 
    redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Collections.singletonList(lockKey), uuid); 
  } 
}
  1. 布隆过滤器(防穿透)
java 复制代码
RBloomFilter<String> bloomFilter = redisson.getBloomFilter("user-filter");
bloomFilter.tryInit(1_000_000, 0.01); // 100w 容量,1% 误判 
// 初始化合法 ID 
userIds.forEach(id -> bloomFilter.add(id)); 
// 查询时先过过滤器 
if (!bloomFilter.contains(requestUserId)) { 
  throw new RuntimeException("非法 ID"); 
}
  1. 雪崩 + 击穿双保险
  • 随机 TTL:ttl = base + Random(0~600) 打散过期

  • 热点永不过期 + 异步刷新: 设置物理过期 = 逻辑过期 + 30min,后台线程提前 10min 更新缓存 。

五、黑科技:把缓存玩成"中间件"

1. 双写一致性 → 基于 Canal 的异步最终一致

  1. MySQL 开 binlog

  2. Canal 监听变更 → MQ → 应用更新 Redis 结果:应用只写 DB,缓存零耦合,延迟 <1s。

2. 大 Key 实时扫描 + 自动拆分

java 复制代码
// 利用 MEMORY USAGE 命令扫描 
public List<BigKeyInfo> scanBigKeys() { 
  Cursor<byte[]> cursor = redisTemplate.executeWithStickyConnection( conn -> conn.scan(ScanOptions.scanOptions().count(1000).build())); 
  List<BigKeyInfo> big = new ArrayList<>(); 
  while (cursor.hasNext()) { 
    String k = new String(cursor.next()); 
    long mem = redisTemplate.execute( (RedisCallback<Long>) con -> con.memoryUsage(k.getBytes())); 
    if (mem > 1024 * 1024) big.add(new BigKeyInfo(k, mem)); 
  } return big; 
}

发现后 按日期/哈希拆表 或改用 redis.hset 分桶 。

3. Pipeline 批量打榜(万次读写 1s 完成)

java 复制代码
List<Object> pipe = redisTemplate.executePipelined((RedisCallback<Object>) conn -> { 
  for (int i = 0; i < 10000; i++) { 
    conn.setEx(("key" + i).getBytes(), 300, ("val" + i).getBytes()); 
  } return null; 
});

单条 1ms → 批量 0.1μs,QPS 提升 100+ 倍 。

4. Redis + Lua 实现秒杀库存扣减(原子 + 0 超卖)

java 复制代码
-- stock.lua 
local stock = tonumber(redis.call('get', KEYS[1])) 
if stock <= 0 then return -1 end 
redis.call('decr', KEYS[1]) 
return stock

Java 侧仅一次 redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), keys),网络 RTT 最小化。

5. 二级缓存(本地 Caffeine + Redis)

思路:L1 进程级 μs,L2 全局共享;L1 miss → L2 → DB,L2 变更发广播清 L1。 实现:Spring Cache 支持多提供者,开箱即用。

六、常见翻车现场 & 急救方案

问题 现象 急救药
缓存雪崩 瞬时 QPS 全打 DB 随机 TTL + 热点永不过期 + 异步刷新
缓存穿透 非法 ID 持续请求 布隆过滤器 + 空值缓存
缓存击穿 热点 Key 失效瞬间 互斥锁(setIfAbsent)+ 逻辑过期
大 Key 阻塞主从同步 扫描拆分,用 hash/分桶
双写不一致 DB≠缓存 延迟双删 / Canal 异步最终一致

七、总结脑图(文字版)

XML 复制代码
Java-Redis 缓存 
├─ 4 种模式:Aside / Read|Write Through / Write Behind 
├─ Spring 落地:@Cacheable + RedisTemplate 
├─ 高并发三件套:分布式锁 + 布隆过滤器 + 雪崩/击穿防护 
└─ 黑科技:Canal 异步一致 / 大 Key 自动拆 / Pipeline 批量 / Lua 0 超卖 / 二级缓存

收藏这篇,面试、调优、高并发都能打!

相关推荐
Anastasiozzzz3 小时前
Java Lambda 揭秘:从匿名内部类到底层原理的深度解析
java·开发语言
骇客野人3 小时前
通过脚本推送Docker镜像
java·docker·容器
铁蛋AI编程实战3 小时前
通义千问 3.5 Turbo GGUF 量化版本地部署教程:4G 显存即可运行,数据永不泄露
java·人工智能·python
IT陈图图4 小时前
CANN生态数据引擎:minddata的缓存策略与性能调优
缓存·cann
晚霞的不甘4 小时前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
SunnyDays10114 小时前
使用 Java 冻结 Excel 行和列:完整指南
java·冻结excel行和列
摇滚侠4 小时前
在 SpringBoot 项目中,开发工具使用 IDEA,.idea 目录下的文件需要提交吗
java·spring boot·intellij-idea
云姜.4 小时前
java多态
java·开发语言·c++
李堇4 小时前
android滚动列表VerticalRollingTextView
android·java
泉-java4 小时前
第56条:为所有导出的API元素编写文档注释 《Effective Java》
java·开发语言