1.什么是缓存穿透
缓存后,不再存在ID访问数据库
布隆过滤器
我们假设ID缓存了,经过HASH计算,得到0000000000111111111这样的。那么布隆内部维护了一堆数组,将对应号位的置1
下次再次hash,如果全是1就代表存在
也会存在hash冲突,解决方法增加数组长度,多次has
2.什么是缓存击穿
热点数据设了过期key,刚好大并发来了,直接击穿
1.加锁
2.异步更新
线程来了,发现过期了,但是照常返回,然后异步更新缓存。
会有旧数据问题
3.缓存雪崩
key的过期时间一致,时间到了,并发冲烂,随机时间
4.redis做为缓存,mysql的数据如何与redis进行同步呢?( 双写一致性 )
线程中断,导致旧数据
1.加锁
读写锁
Redisson
在读的时候添加共享锁,可以保证读读不互斥、读写互斥。当我们更新数据的时候,添加排他锁。它是读写、读读都互斥,这样就能保证在写数据的同时,是不会让其他线程读数据的,避免了脏数据。这里面需要注意的是,读方法和写方法上需要使用同一把锁才行。

其实排他锁底层使用的也是SETNX,它保证了同时只能有一个线程操作锁住的方法。
- 读锁 :
- 加锁条件:当前没有线程持有写锁;
- 释放后:只要没有读锁了,写锁就能竞争。
- 写锁 :
- 加锁条件:当前没有任何线程持有读锁 或写锁;
- 释放后:读锁和写锁都能竞争。
2.mq+canal

当数据库发生修改,cancl类似从库的机制监听文件,如果发送改变,到达mq,mq进行接收。然后进行处理。可能会有旧数据
3.延时双删
删除时间不好确定,改页不好改,容易导致旧数据污染,
5.Redis持久化
在Redis中提供了两种数据持久化的方式:1) RDB;2) AOF。
:RDB因为是二进制文件,保存时体积也比较小,所以它恢复得比较快。但它有可能会丢数据。
bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB
我们通常在项目中也会使用AOF来恢复数据。虽然AOF恢复的速度慢一些,但它丢数据的风险要小很多。在AOF文件中可以设置刷盘策略。我们当时设置的就是每秒批量写入一次命令。
每隔几秒读取新的命令文件、
RDB块 AOF慢

6.Redis过期策略
惰性删除
懒加载,执行key操作前查询
定时删除
某一段时间查询
SLOW模式,是定时任务,执行频率默认为10hz,每次不超过25ms,可以通过修改配置文件redis.conf的hz选项来调整这个次数;
- FAST模式,执行频率不固定,每次事件循环会尝试执行,但两次间隔不低于2ms,每次耗时不超过1ms。
Redis的过期删除策略是:惰性删除 + 定期删除两种策略配合使用。
7.Redis过期淘汰策略
Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。

LRU
最近后访问就删最近后
LFU
热点数据淘汰法


8.Redis分布式锁的实现
SETNX
给指定 key 设置值,仅当 key 不存在时成功(返回 1),key 已存在则失败(返回 0); 原子性操作
如果一直获取锁怎么办呢
Redisson框架

如果业务代码卡在循环里一直不结束,Redisson 的看门狗确实会一直给锁续期,直到线程本身被终止。
偏向锁 → 轻量级锁 → 重量级锁
在高并发下,一个业务有可能会执行很快。客户1持有锁的时候,客户2来了以后并不会马上被拒绝。它会自旋不断尝试获取锁。如果客户1释放之后,客户2就可以马上持有锁,性能也得到了提升。
轻量级锁机制
Redisson实现的 分布式锁 是可重入的吗 ?
是可重入的
如果是当前线程持有锁就会+1

防止死锁
如果有多台redis做主从呢

RedLock(红锁):不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁(n / 2 + 1),避免在一个redis实例上加锁。

效率过低
zookeeper推荐
Redlock 是 Redis 官方推荐的多节点分布式锁算法,核心思路是:在多个独立的 Redis 节点(至少 3 个)上同时加锁,只有超过半数节点加锁成功,才算整体加锁成功,解决单节点故障导致锁失效的问题。
import org.redisson.RedissonRedLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
public class RedissonRedLockDemo {
// 多个独立的 Redis 客户端(连接不同的 Redis 节点)
private final RedissonClient redissonClient1;
private final RedissonClient redissonClient2;
private final RedissonClient redissonClient3;
public RedissonRedLockDemo(RedissonClient client1, RedissonClient client2, RedissonClient client3) {
this.redissonClient1 = client1;
this.redissonClient2 = client2;
this.redissonClient3 = client3;
}
public void doBusinessWithRedLock() {
// 1. 获取每个 Redis 节点的锁对象
RLock lock1 = redissonClient1.getLock("business_lock");
RLock lock2 = redissonClient2.getLock("business_lock");
RLock lock3 = redissonClient3.getLock("business_lock");
// 2. 构建 RedLock(整合多节点锁)
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
try {
// 3. 加锁:必须指定 leaseTime(禁用续期,避免多节点续期不一致)
// waitTime:最多等5秒拿锁,leaseTime:锁最多持有30秒
boolean locked = redLock.tryLock(5, 30, TimeUnit.SECONDS);
if (!locked) {
throw new RuntimeException("多节点加锁失败,放弃执行");
}
// 执行业务逻辑(多节点锁保证分布式环境下的原子性)
System.out.println("RedLock 加锁成功,执行业务...");
Thread.sleep(1000); // 模拟业务耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("加锁被中断", e);
} finally {
// 4. 释放锁(会同时释放所有节点的锁)
if (redLock.isHeldByCurrentThread()) {
redLock.unlock();
System.out.println("RedLock 释放成功");
}
}
}
}
Redis 集群 / 主从
主死亡,从顶上
Redis集群
主从复制、哨兵模式、Redis分片集群。
1.主从同步
全量同步到增量同步
主写从读

