一、缓存穿透
(1)介绍
大量请求的 key 是不合理的,根本不存在于缓存中,也不存在于数据库中 。这就导致这些请求直接到了数据库上,根本没有经过缓存这一层,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。
java----[IO]----Redis----[IO]---DB[数据库]
1.客户端大量读数据(缓存中没有对应数据)
2.大量读请求落到数据库上(数据库中没有对应的数据)
(2)解决操作
最基本的:做好参数校验
1、使用布隆过滤器:
布隆过滤器是一种空间效率高的概率数据结构,用于判断某个元素是否在集合中。可以在请求到达数据库之前,先通过布隆过滤器进行判断,如果不在集合中,则直接返回。
【一个key同时满足三个hash都是同一个key--------进行校验】
Bloom Filter 会使用一个较大的bit数组,数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1(代表 false 或者 true),这也是 Bloom Filter 节省内存的核心所在。(基于内存)
2、接口限流
限流与熔断:对于频繁请求的数据,可以通过限流和熔断机制来控制流量,减少对数据库的压力。
根据用户或者 IP 对接口进行限流,对于异常频繁的访问行为,还可以采取黑名单机制,例如将异常 IP 列入黑名单。
二、缓存击穿
(1)介绍
缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。这就可能会导致瞬时大量的请求直接打到了数据库上,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。
(2)解决操作
1、永不过期(不推荐)
设置热点数据永不过期或者过期时间比较长。
2、提前预热(推荐)
针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
3、加锁(看情况)
在缓存失效后,通过设置互斥锁确保只有一个请求去查询数据库并更新缓存。
三、缓存雪崩
(1)介绍
缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力。
另外,缓存服务宕机也会导致缓存雪崩现象,导致所有的请求都落到了数据库上。
Redis持久化机制详解
Redis 不同于 Memcached 的很重要一点就是,Redis 支持持久化,而且支持 3 种持久化方式:
- 快照(snapshotting,RDB)
- 只追加文件(append-only file, AOF)
- RDB 和 AOF 的混合持久化(Redis 4.0 新增)
- Redis 提供了多种持久化机制,以确保数据在系统重启或故障后能够恢复。主要的持久化方式有两种:RDB(快照)和 AOF(追加文件)。
一、RDB
RDB 是 Redis 将内存中的数据快照存储到磁盘上的文件形式。默认情况下,快照以 .rdb
文件存储。
工作原理:
Redis 会根据配置的时间间隔和修改次数自动生成快照。比如,可以配置为每 60 秒保存一次,如果超过 100 次写操作。
优点:
启动速度快:由于是二进制格式,RDB 文件较小,加载速度较快。
性能开销小:在生成快照时,只会影响到快照生成的瞬间,不会影响正常的读写性能。
缺点:
数据丢失风险:如果 Redis 在快照生成后崩溃,可能会丢失最后一段时间内未持久化的数据。
二、AOF
AOF 持久化功能的实现可以简单分为 5 步:
- 命令追加(append):所有的写命令会追加到 AOF 缓冲区中。
- 文件写入(write):将 AOF 缓冲区的数据写入到 AOF 文件中。这一步需要调用
write
函数(系统调用),write
将数据写入到了系统内核缓冲区之后直接返回了(延迟写)。注意!!!此时并没有同步到磁盘。 - 文件同步(fsync):AOF 缓冲区根据对应的持久化方式(
fsync
策略)向硬盘做同步操作。这一步需要调用fsync
函数(系统调用),fsync
针对单个文件操作,对其进行强制硬盘同步,fsync
将阻塞直到写入磁盘完成后返回,保证了数据持久化。 - 文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
- 重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复。