Redis 使用场景
1. 使用场景的问题
a. 缓存问题
-
缓存穿透:查询不存在的数据,MySQL 查询不到数据也不会直接写入缓存,导致每次查询都访问数据库。
解决方法:缓存空数据、布隆过滤器。 -
缓存击穿:给某个 key 设置了过期时间,当 key 过期时,恰好有大量并发请求发过来,这些请求可能会把数据库压垮。
解决方法:互斥锁(PV),逻辑过期:给热点数据不设置过期时间,而是使用一个expire
的特殊字段。 -
缓存雪崩:同一时间内大量缓存的 key 失效(过期),或者 Redis 服务宕机,导致大量请求到达数据库,带来巨大压力。
解决方法:- 如果是由于同时到期影响的,可以设置不同 key 的失效期限;
- 如果是服务宕机,则可以提高 Redis 集群服务:哨兵模式、集群模式;
- 给缓存业务加降级限流策略:Nginx、Spring Cloud Gateway;
- 给业务添加多级缓存,除了 Redis 之外的缓存。
-
双写一致问题(MySQL 与 Redis 数据同步):如何保证 MySQL 与 Redis 的一致性?
解决方法:- 延时双删:删除缓存 -> 修改数据库 -> 延时后删除缓存(弱一致性);
- 互斥锁;
- 折中法:读多写少放入缓存,写的直接操作数据库。
-
持久化问题:Redis 做缓存怎么实现数据持久化?
- RDB:Redis 的数据备份文件,也叫 Redis 快照,将所有数据都记录在磁盘上。如果发生故障重启,从磁盘读取文件恢复数据。
- AOF:追加文件,记录每个写操作日志,数据丢失较少,但日志文件较大。
-
数据过期策略:“加入 Redis 数据过期会立即删除吗”?
- 惰性删除:过期之后不删除,直到访问时再检查是否过期,过期则删除。占用内存。
- 定期删除:每隔一段时间对 key 检查,确保不占用内存。删得太频繁对 CPU 不友好,删得少则占内存,Redis 做了折中。
-
数据淘汰策略:“加入内存满了,Redis 怎么办”?
- 默认:不淘汰,内存满了不允许写入新数据。
- 比较 TTL(有效期)适用于有时间期限的数据。
- 随机淘汰所有数据(包括对 TTL 的数据和全局数据)。
- LRU(最近最少使用)、LFU(最不常用)淘汰算法。
b. 分布式锁问题
-
分布式锁场景:定时任务、抢单、幂等性场景。
用于解决分布式加锁的问题,因为一个服务可能在不同服务器分布式运行。 -
分布式锁实现方法:
- 使用
setnx
(SET if Not eXists)指令; - 使用 Redis 客户端库如 Redisson。
- 使用
2. Redis 集群方案
a. 主从模式
- 单点的 Redis 并发能力有限,要提高并发能力,可以搭建主从集群,实现读写分离。
缺点:主节点宕机会导致服务不可用。
b. 哨兵模式
- 提供自动故障恢复机制。监控 Redis 服务的状态,若主节点出现故障,则自动切换一个从节点为主节点,并通知客户端连接新主节点。
c. 分片集群
- 解决海量数据问题,通过分片将数据分散到多个 Redis 实例中进行存储,能够有效提升系统的扩展性。