【缓存策略】你知道 Cache Aside(缓存旁路)这个缓存策略吗
👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主
⛪️ 个人社区:个人社区
💞 个人主页:个人主页
🙉 专栏地址: ✅ Java 中级
🙉八股文专题:剑指大厂,手撕 Java 八股文
文章目录
- 1. 缓存策略 Cache Aside 是什么?
- 2. 缓存策略 Cache Aside 的应用场景
- 3. 缓存策略 Cache Aside 的优缺点
- 4. 用 Java 模拟使用 Cache Aside 策略
- 1. 引入依赖
- 2. 配置 Redis
- 3. 创建缓存服务
- 4. 创建用户服务
- 5. 创建控制器
- 6. 启动类
1. 缓存策略 Cache Aside 是什么?
Cache Aside(缓存旁路) 是一种常见的缓存策略,其核心思想是在读取数据时,先从缓存中读取,如果缓存中没有数据,则从数据库中读取,并将数据写入缓存;在写入数据时,直接更新数据库,并从缓存中移除该数据。
具体步骤:
-
读取数据:
- 尝试从缓存中读取数据。
- 如果缓存中存在数据,直接返回。
- 如果缓存中不存在数据,从数据库中读取数据。
- 将从数据库中读取的数据写入缓存,然后返回数据。
-
写入数据:
- 直接更新数据库。
- 从缓存中移除该数据,以避免缓存中的数据与数据库中的数据不一致。
2. 缓存策略 Cache Aside 的应用场景
Cache Aside 适用于以下场景:
- 读多写少:适用于读取操作远多于写入操作的场景,如新闻网站的文章阅读。
- 数据更新不频繁:适用于数据更新不频繁,但读取非常频繁的场景。
- 数据一致性要求不高:适用于对数据一致性要求不高的场景,可以容忍短暂的数据不一致。
- 高并发读取:适用于高并发读取的场景,可以显著减轻数据库的负载。
3. 缓存策略 Cache Aside 的优缺点
优点:
- 性能提升:通过缓存减少对数据库的访问次数,提高读取性能。
- 减轻数据库压力:减少数据库的读取请求,减轻数据库的负载。
- 灵活性:可以在不修改业务逻辑的情况下,通过缓存策略提升系统性能。
缺点:
- 数据不一致:在写入数据后,缓存中的数据可能已经过期,导致短暂的数据不一致。
- 缓存击穿:如果大量请求同时访问同一个缓存键,而该键在缓存中不存在,会导致大量请求直接打到数据库,造成数据库压力。
- 缓存雪崩:如果缓存中的数据在同一时间过期,大量请求会同时打到数据库,造成数据库压力。
4. 用 Java 模拟使用 Cache Aside 策略
下面是一个简单的 Java 示例,模拟使用 Cache Aside 策略。
1. 引入依赖
在 pom.xml
中添加 Redis 依赖(假设使用 Redis 作为缓存):
<dependencies>
<!-- Spring Boot Starter Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2. 配置 Redis
在 application.properties
中配置 Redis:
spring.redis.host=localhost
spring.redis.port=6379
3. 创建缓存服务
创建一个服务类来实现 Cache Aside 策略:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class CacheService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private UserService userService;
public String getUserById(String userId) {
// 尝试从缓存中读取数据
String cachedUser = redisTemplate.opsForValue().get(userId);
if (cachedUser != null) {
return cachedUser;
}
// 如果缓存中没有数据,从数据库中读取
String user = userService.getUserById(userId);
if (user != null) {
// 将数据写入缓存
redisTemplate.opsForValue().set(userId, user);
}
return user;
}
public void updateUser(String userId, String userName) {
// 直接更新数据库
userService.updateUser(userId, userName);
// 从缓存中移除该数据
redisTemplate.delete(userId);
}
}
4. 创建用户服务
创建一个简单的用户服务类,模拟数据库操作:
import org.springframework.stereotype.Service;
@Service
public class UserService {
public String getUserById(String userId) {
// 模拟从数据库中读取用户数据
// 实际应用中,这里应该是数据库查询操作
return "User: " + userId;
}
public void updateUser(String userId, String userName) {
// 模拟更新数据库中的用户数据
// 实际应用中,这里应该是数据库更新操作
System.out.println("Updating user: " + userId + " to " + userName);
}
}
5. 创建控制器
创建一个控制器类,提供 RESTful API 接口:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private CacheService cacheService;
@GetMapping("/user")
public String getUser(@RequestParam String id) {
return cacheService.getUserById(id);
}
@PostMapping("/user")
public String updateUser(@RequestParam String id, @RequestParam String name) {
cacheService.updateUser(id, name);
return "User updated: " + id + " to " + name;
}
}
6. 启动类
创建一个启动类来启动 Spring Boot 应用:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CacheAsideApplication {
public static void main(String[] args) {
SpringApplication.run(CacheAsideApplication.class, args);
}
}
运行项目
-
启动 Redis 服务器:
- 确保 Redis 服务器正在运行,可以通过命令
redis-server
启动。
- 确保 Redis 服务器正在运行,可以通过命令
-
启动 Spring Boot 应用:
- 运行
CacheAsideApplication
类的main
方法,启动 Spring Boot 应用。
- 运行
-
测试接口:
- 使用 Postman 或浏览器测试接口:
GET http://localhost:8080/user?id=1
:读取用户数据。POST http://localhost:8080/user?id=1&name=JohnDoe
:更新用户数据。
- 使用 Postman 或浏览器测试接口:
精彩专栏推荐订阅:在下方专栏👇🏻
✅ 2023年华为OD机试真题(A卷&B卷)+ 面试指导
✅ 精选100套 Java 项目案例
✅ 面试需要避开的坑(活动)
✅ 你找不到的核心代码
✅ 带你手撕 Spring
✅ Java 初阶