使用Redis实现分布式缓存
分布式缓存是一种设计思想。
分布式缓存是指将缓存数据分布存储在 多台服务器 上,以便在高并发场景下提供更高的吞吐量和更好的容错性。
通常使用Redis实现
使用 Redis 实现分布式缓存,典型流程可以理解为:
应用先查 Redis,Redis 没有再查数据库,然后把结果写回 Redis。
基本流程
-
用户请求进入应用服务
比如用户查询商品详情:
GET /products/1001 -
应用先查询 Redis 缓存
应用根据业务生成一个缓存 Key,例如:
product:1001然后查询 Redis:
GET product:1001 -
如果 Redis 中有数据,直接返回
这叫 缓存命中。
用户请求 ↓ 应用服务 ↓ Redis 有数据 ↓ 直接返回结果优点是速度快,不需要访问数据库。
-
如果 Redis 中没有数据,查询数据库
这叫 缓存未命中。
用户请求 ↓ 应用服务 ↓ Redis 没有数据 ↓ 查询数据库 -
将数据库查询结果写入 Redis
数据库查到结果后,应用把数据写入 Redis,并设置过期时间:
SET product:1001 "{商品数据}" EX 3600表示缓存 1 小时。
-
返回数据给用户
最后应用把数据库查到的数据返回给用户。
完整流程如下:
用户请求
↓
应用服务
↓
查询 Redis
↓
Redis 是否有数据?
↓
有数据 ----------------→ 直接返回
↓
没有数据
↓
查询数据库
↓
写入 Redis,并设置过期时间
↓
返回结果
简单 Java 示例
public Product getProductById(Long id) {
String key = "product:" + id;
// 1. 先查 Redis
Product product = redisTemplate.opsForValue().get(key);
if (product != null) {
// 2. 缓存命中,直接返回
return product;
}
// 3. 缓存未命中,查数据库
product = productMapper.selectById(id);
if (product != null) {
// 4. 写入 Redis,并设置过期时间
redisTemplate.opsForValue().set(key, product, 1, TimeUnit.HOURS);
}
return product;
}
常见缓存策略
-
Cache Aside Pattern,旁路缓存模式
最常见,也是上面这个流程:
读:先查缓存,缓存没有查数据库,再写缓存 写:先更新数据库,再删除缓存 -
设置过期时间
防止 Redis 中的数据长期不更新:
product:1001 过期时间 1 小时 -
更新数据时删除缓存
修改商品信息时,通常这样做:
更新数据库 ↓ 删除 Redis 缓存而不是直接更新缓存。
写操作流程
比如修改商品价格:
用户修改商品信息
↓
应用服务
↓
更新数据库
↓
删除 Redis 中对应缓存
↓
下次查询时重新加载新数据到 Redis
示例:
public void updateProduct(Product product) {
// 1. 更新数据库
productMapper.updateById(product);
// 2. 删除缓存
String key = "product:" + product.getId();
redisTemplate.delete(key);
}
使用 Redis 做分布式缓存时要注意的问题
-
缓存穿透
查询一个数据库中也不存在的数据,导致每次都查数据库。
解决方式:
缓存空值 / 布隆过滤器 -
缓存击穿
某个热点 Key 过期,大量请求同时打到数据库。
解决方式:
加互斥锁 / 热点数据不过期 / 提前刷新 -
缓存雪崩
大量 Key 同时过期,数据库压力突然增大。
解决方式:
过期时间加随机值 / 多级缓存 / 限流降级 -
数据一致性
数据库和 Redis 可能短时间不一致。
常见做法:
先更新数据库,再删除缓存
Redis 分布式缓存的核心流程就是:读数据先查缓存,缓存没有查数据库并写回缓存;写数据先更新数据库,再删除缓存。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)