Redis 缓存入门
1. 一句话简介
Redis 是一个基于内存的高性能键值存储系统,可同时作为缓存、消息队列和轻量级数据库使用,核心价值是将高频访问的数据从磁盘数据库搬到内存中,把单次读取的耗时从毫秒级降到亚毫秒级。Spring Boot 通过 spring-boot-starter-data-redis 提供自动配置,既能用 RedisTemplate 直接操作数据,也能通过 Spring Cache 的 @Cacheable、@CachePut、@CacheEvict 注解无侵入地接入缓存。以本模块为例,UserServiceImpl 只需在 get 方法上加 @Cacheable(value = "user", key = "#id"),首次查询后结果即被缓存到 Redis,后续相同查询直接命中缓存而不进入方法体,日志中不再出现查询打印。
2. 什么时候使用
- ✅ 多实例部署,需要缓存共享:本地缓存(如 Ehcache)各自存在于每个 JVM 内,多实例间不共享。Redis 作为独立服务,所有应用实例共享同一份缓存,本模块正是为此从 Ehcache 切换到 Redis。
- ✅ 读多写少的热点数据:如用户画像、配置、商品详情等被频繁读取但很少变化的数据,缓存命中可显著降低数据库压力。
- ✅ 需要丰富数据结构的存储:Redis 原生支持 String、Hash、List、Set、ZSet、GEO 等结构(对应
RedisTemplate的opsForValue、opsForHash、opsForList、opsForSet、opsForZSet、opsForGeo),可在同一种技术里完成计数、排行榜、地理位置等多种需求。 - ✅ 需要高并发下的原子能力:本模块用 1000 个线程同时对
count执行increment,Redis 的INCR命令是原子的,最终值恰好为 1000,无需在应用层加锁。 - ✅ 缓存数据需持久化、可跨语言读取:Redis 用 JSON 序列化(
GenericJackson2JsonRedisSerializer)存储,既能在redis-cli中直接查看,也能被任何语言解析。 - ❌ 单机应用、数据体量极小:若只有单个实例且缓存数据量可控,引入独立 Redis 服务反而增加运维成本,本地缓存即可满足。
- ❌ 冷数据或一次性的临时数据:存入缓存却没有复用价值,只会白白占用内存,还会增加缓存与数据库的一致性维护成本。
- ❌ 强一致性的金融/账务类数据:Redis 本质是最终一致、易失的缓存,无法替代数据库的事务与持久化保障。
- ❌ 超大对象或超大缓存量:Redis 是内存型存储,容量受内存限制且成本高,超大缓存需考虑热数据裁剪、内存淘汰策略。
- ❌ 对缓存一致性要求极高的场景:引入缓存后需处理缓存雪崩、穿透、击穿及双写一致性问题,特别是多实例同时更新同一 key 时易出现脏读,需谨慎设计失效与更新策略。
3. 常见业务场景
用户信息缓存:以用户 ID 为主键,查询用户时先查缓存再查数据库。本模块的 get 方法用 @Cacheable(value="user", key="#id") 缓存用户对象,用 @CachePut 在保存/更新时同步刷新缓存,用 @CacheEvict 在删除时清除缓存,完整演示了缓存的增删改查闭环,是典型的按主键缓存业务实体。
热点数据防穿透:对于商品详情、文章内容、首页配置等高频读取的只读数据,缓存命中后直接返回,避免同一热点反复打到数据库。配合设置过期时间或空值缓存可缓解缓存穿透问题。
并发计数与秒杀库存:利用 Redis INCR/DECR 命令的原子性实现点赞数、访问量、库存扣减。本模块 1000 线程并发 increment("count", 1) 结果精确为 1000,说明其在高并发计数上无需应用层锁即可保证正确性。
Session 共享与登录态:多实例负载均衡时,各实例本地 Session 互不相同。将 Session 存入 Redis(key 关联登录 token),所有实例都能读取同一登录态,实现无状态集群。
排行榜与热门列表:利用 ZSet 有序集合按分数排序,天然适合做排行榜、最近热榜、TOP N 等需要按分值动态排序的场景,这是普通 Key-Value 缓存和关系型数据库排序开销大的场景下 Redis 的独特优势。
4. 同类技术对比
| 维度 | Redis | Ehcache | Caffeine | Memcached |
|---|---|---|---|---|
| 存储位置 | 独立网络服务(内存) | 嵌于应用 JVM 内 | 嵌于应用 JVM 内 | 独立网络服务(内存) |
| 多实例共享 | 支持,所有实例共享 | 不支持,各 JVM 独立 | 不支持,各 JVM 独立 | 支持,可多实例共享 |
| 数据结构 | String、Hash、List、Set、ZSet、GEO | 仅 Key-Value | 仅 Key-Value | 仅 Key-Value |
| 持久化 | 支持 RDB 快照 + AOF 日志 | 支持磁盘溢出 | 不支持(纯内存) | 不支持(纯内存) |
| 网络开销 | 需走网络,单次约 0.1~1ms | 无网络开销,直接内存访问 | 无网络开销,极快 | 需走网络,性能近于 Redis |
| 分布式/集群能力 | 主从、哨兵、Cluster,能力强 | 无 | 无 | 分布式,但无 Redis 丰富 |
| 学习成本与配置 | 需单独部署与运维,成本较高 | 低,仅引入依赖与配置 | 低,上手快 | 中,需单独部署 |
| 适用规模 | 分布式系统、大数据量 | 单机应用、读多写少 | 单 JVM 高性能本地缓存 | 分布式 Key-Value 缓存 |
选型建议:多实例部署、需要缓存共享的场景首选 Redis,它是分布式缓存的事实标准,且数据结构丰富,可一技术多用;若只是单机应用求极致的本地缓存性能,选 Caffeine(性能优于 Ehcache);需要缓存可溢出到磁盘、逻辑相对简单时可考虑 Ehcache;仅需纯 Key-Value 分布式缓存的简单场景可选 Memcached,但它在数据结构和持久化上弱于 Redis。整体而言,生产环境多实例系统优先 Redis,单机可叠加本地缓存(Caffeine/Ehcache)作为 L1 与 Redis 作为 L2 形成多级缓存。