目标:掌握分布式缓存的基本概念,学习如何使用 Redis 缓存数据。
理论知识
1. 分布式缓存的作用与应用场景
-
作用:
- 提高访问速度:缓存热点数据,减少数据库查询次数。
- 减轻数据库压力:缓解高并发场景下数据库的性能瓶颈。
- 实现分布式架构:通过缓存共享数据,支持分布式系统。
-
应用场景:
- 热点数据查询(如商品详情、用户信息)。
- 会话管理(如分布式 Session)。
- 计数器(如点赞数、访问量)。
2. Redis 的基本概念
-
Redis 是什么:
- 高性能的内存数据库,支持多种数据结构。
- 支持持久化,将数据存储到磁盘,避免数据丢失。
-
常用数据类型:
- String:简单的键值对。
- List:链表,支持队列和栈操作。
- Set:集合,支持去重和交并差集操作。
- Hash:哈希表,适合存储对象数据。
- Sorted Set:有序集合,支持排序。
3. 缓存常见问题与解决方案
-
缓存穿透:
- 问题:查询的 key 不存在,直接穿透到数据库。
- 解决方案:对空值进行缓存,或者使用布隆过滤器。
-
缓存雪崩:
- 问题:大量缓存同时过期,导致请求涌入数据库。
- 解决方案:为缓存设置随机过期时间,避免同时失效。
-
缓存击穿:
- 问题:热点 key 过期,瞬时高并发请求击穿缓存。
- 解决方案:使用互斥锁(分布式锁)保护缓存重建。
4. Redis 与数据库结合使用
-
典型场景:
- 查询数据时,先查缓存,再查数据库。
- 数据更新时,及时更新缓存,或使用延迟双删策略。
-
流程:
- 查询缓存,如果命中则直接返回。
- 如果未命中,查询数据库并将结果写入缓存。
- 设置缓存过期时间,保持数据一致性。
实践操作
1. 配置 Redis 客户端
-
安装 Redis:
- 使用 Docker 安装 Redis:
docker run -d --name redis -p 6379:6379 redis
- 添加依赖: 在
pom.xml
中添加 Redis 的客户端依赖(推荐使用 Lettuce):<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
- 配置 Redis: 在
application.yml
中配置 Redis 的连接信息:spring: redis: host: localhost port: 6379 lettuce: pool: max-active: 8 max-idle: 8 min-idle: 0 timeout: 2000ms
- 使用 Docker 安装 Redis:
-
使用 Redis 缓存数据
2.1 创建 Redis 工具类
使用
RedisTemplate
操作 Redis:import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; @Component public class RedisUtil { @Autowired private RedisTemplate<String, Object> redisTemplate; // 写入缓存 public void set(String key, Object value, long timeout) { redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS); } // 读取缓存 public Object get(String key) { return redisTemplate.opsForValue().get(key); } // 删除缓存 public void delete(String key) { redisTemplate.delete(key); } }
2.2 缓存用户信息
创建一个简单的用户管理服务,利用 Redis 缓存用户数据:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.Map; @Service public class UserService { @Autowired private RedisUtil redisUtil; private static final String USER_CACHE_KEY_PREFIX = "user:"; // 模拟数据库 private static final Map<Long, String> DATABASE = new HashMap<>(); static { DATABASE.put(1L, "Alice"); DATABASE.put(2L, "Bob"); DATABASE.put(3L, "Charlie"); } // 获取用户信息 public String getUserById(Long userId) { String cacheKey = USER_CACHE_KEY_PREFIX + userId; // 查询缓存 Object cachedUser = redisUtil.get(cacheKey); if (cachedUser != null) { return (String) cachedUser; } // 查询数据库 String user = DATABASE.get(userId); if (user != null) { redisUtil.set(cacheKey, user, 300); // 缓存 5 分钟 } return user; } }
2.3 测试接口
创建一个 Controller,提供用户查询接口:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/user") public String getUser(@RequestParam Long userId) { return userService.getUserById(userId); } }
总结
-
理论掌握:
- 分布式缓存的作用与 Redis 的基本概念。
- 缓存穿透、缓存雪崩、缓存击穿的解决方案。
-
实践收获:
- 使用 Spring Boot 集成 Redis,实现数据的缓存。
- 通过
RedisTemplate
实现缓存的增删查操作。
-
进一步扩展:
- 学习 Redis 的高级特性,如事务、Lua 脚本和分布式锁。
- 在实际项目中结合 Redis 哨兵模式或集群部署,提升可用性和性能。