继续学习redis05-08,大家一起加油哇!!
Redis
5.缓存-持久化
- redis作为缓存,数据的持久化是怎么做的?
1.RDB
RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据
以下这两种命令,都是人工主动备份:
[root@localhost ~]# redis-cli
127.0.0.1:6379>save #由Redis主进程来执行RDB,会阻塞所有命令
ok
127.0.0.1:6379> bgsave #开启子进程执行RDB,避免主进程受到影响
Background saving started
(无需人工,使用子进程)redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:
#900秒内,如果至少有1个key被修改,则执行bgsave
save 900 1
save 300 10
save 60 10000
- RDB的执行原理?
bgsave开始时会fork(克隆)主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB文件。
fork采用的是copy-on-write技术:
- 当主进程执行读操作时,访问共享内存;
- 当主进程执行写操作时,则会拷贝一份数据,执行写操作。
页表:记录虚拟地址与物理地址的映射关系
写操作很多 → 会不会拷贝很多次?
不会拷贝很多“份数据”,只会拷贝很多“被写到的页”。
这是一种 “按需、增量、页级别”复制机制。
RDB 拷贝 = 不是 Key 级 = 不是对象级 = 是【内存页级(4KB)】
理论最坏情况: RDB期间几乎所有内存页都被写过→ 内存占用 ≈ 原数据 × 2 因此官方文档强调:Redis 需要预留足够的内存来支持 fork + COW
2.AOF
AOF全称为Append Only File(追加文件)。redis处理的每一个写命令都会记录在AOF文件,可以看作是命令日志文件。
[root@localhost redis-6.2.4]# redis-cli
127.0.0.1:6379> set num 123
OK
AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:
#是否开启AOF功能,默认是no
appendonly yes
#AOF文件的名称
appendfilename "appendonly.aof"
AOF的命令记录的频率也可以通过redis.conf文件来配:(一般使用everysec)
设置刷盘策略:
#表示每执行一次写命令,立即记录到AOF文件
appendfsync always
#写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec
#写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no
| 配置项 | 刷盘时机 | 优点 | 缺点 |
|---|---|---|---|
| always | 同步刷盘 | 可靠性高,几乎不丢数据 | 性能影响大 |
| everysec | 每秒刷盘 | 性能适中 | 最多丢失1秒数据 |
| no | 操作系统控制 | 性能最好 | 可靠性差,可能丢失大量数据 |
因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。
Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:
# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写
auto-aof-rewrite-min-size 64mb
RDB与AOF对比
RDB与AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。
| RDB | AOF | |
|---|---|---|
| 持久化方式 | 定时对整个内存做快照 | 记录每一次执行的命令 |
| 数据完整性 | 不完整,两次备份之间会丢失(假如redis宕机) | 相对完整,取决于刷盘策略 |
| 文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积很大 |
| 宕机恢复速度 | 很快 | 慢 |
| 数据恢复优先级 | 低,因为数据完整性不如AOF | 高,因为数据完整性更高 |
| 系统资源占用 | 高,大量CPU和内存消耗 | 低,主要是磁盘IO资源 但AOF重写时会占用大量CPU和内存资源 |
| 使用场景 | 可以容忍数分钟的数据丢失,追求更快的启动速度 | 对数据安全性要求较高常见 |
✅ 面试 / 汇报首选版本
RDB 是对内存中数据状态的快照持久化, AOF 是对 Redis 写命令的日志持久化。
✅ 更对称、也更好记的版本
RDB 持久化的是“结果”, AOF 持久化的是“过程”。
- 如果考官追问一句“那为什么不能说 AOF 是操作?”
因为 AOF 只记录会修改数据的写命令,而不会记录读命令或内部操作,所以严格来说它是写命令日志,而不是所有操作。
6.缓存-数据过期策略
- 假如redis的key过期之后,会立即删除吗?
Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)。
例如:set name heima 10 10秒过后删除
1.惰性删除
惰性删除:设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。
例子:
set name zhangsan 10
get name // 发现name过期了,直接删除key
- 优点:对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查
- 缺点:对内存不友好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存中,内存永远不会释放
2.定期删除
定期删除:每隔一段时间,我们就对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行检查,并删除其中的过期key)。
上
定期清理有两种模式:
● SLOW模式是定时任务,执行频率默认为10hz(每秒执行10次(执行周期是100ms)),每次不超过25ms(不能影响主进程),以通过修改配置文件redis.conf的hz选项来调整这个次数
●FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms
优点:可以通过限制删除操作执行的时长和频率来减少删除操作对CPU的影响。另外定期删除,也能有效释放过期键占用的内存。
缺点:难以确定删除操作执行的时长和频率。
!!redis的过期删除策略:惰性删除 + 定期删除两种策略进行配合使用
总结:
Redis的数据过期策略
-
惰性删除:访问key的时候判断是否过期,如果过期,则删除
-
定期删除:定期检查一定量的key是否过期(SLOW模式+FAST模式)
Redis的过期删除策略:惰性删除+定期删除两种策略进行配合使用
7.缓存-数据淘汰策略
- 假如缓存过多,内存是有限的,内存被占满了怎么办?
数据的淘汰策略:当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。
redis支持8中不同策略来选择要删除的key:
- noeviction:不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略。
#
#The default is:
#
# maxmemory-policy noeviction
-
volatile-ttl:对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰。
-
allkeys-random:对全体key,随机进行淘汰。
-
volatile-random:对设置了TTL的key,随机进行淘汰。
-
allkeys-Iru: 对全体key,基于LRU算法进行淘汰。
-
volatile-Iru:对设置了TTL的key,基于LRU算法进行淘汰。
-
allkeys-Ifu:对全体key,基于LFU算法进行淘汰。
-
volatile-lfu:对设置了TTL的key,基于LFU算法进行淘汰。
-
LRU(Least Recently Used)最近最少使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
例:key1是在3s之前访问的,key2是在9s之前访问的,删除的就是key2
-
LFU(Least Frequently Used)最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。
例:key1最近5s访问了4次,key2最近5s访问了9次,删除的就是key1
-
数据淘汰策略-使用建议
-
优先使用allkeys-Iru策略。充分利用LRU算法的优势,把最近最常访问的数据留在缓存中。如果业务有明显的冷热数据区分,建议使用。
-
如果业务中数据访问频率差别不大,没有明显冷热数据区分,建议使用allkeys-random,随机选择淘汰。
-
如果业务中有置顶的需求,可以使用volatile-lru策略,同时置顶数据不设置过期时间,这些数据就一直不被删除会淘汰其他设置过期时间的数据。
-
如果业务中有短时高频访问的数据,可以使用allkeys-Ifu或 volatile-Ifu策略。
关于数据淘汰策略其他的面试问题
-
数据库有1000万数据,Redis只能缓存20w数据,如何保证Redis中的数据都是热点数据?
使用allkeys-lru(挑选最近最少使用的数据淘汰)淘汰策略,留下来的都是经常访问的热点数据
注:一开始想的是lfu,觉得访问频率越高才对,
在该场景下优先选择 LRU 而不是 LFU,不是因为 LFU 不好,而是 LRU 更符合 Redis 热点数据的“时效性”特征,实现成本更低,稳定性更好。
1️⃣ LRU 解决的问题是:最近是否还在被用
-
判断标准:最近一次访问时间
-
更敏感于 访问趋势变化
-
适合:
- 热点快速变化
- 突发流量
- 业务波动明显
👉 更贴近“实时热点”
2️⃣ LFU 解决的问题是:历史上用得多不多
-
判断标准:累计访问频次
-
强调长期统计
-
适合:
- 热点长期稳定
- 流量分布相对平缓
👉 更贴近“长期热门”
在缓存容量远小于数据总量、且热点变化频繁的场景下,使用 allkeys-lru 更有利于快速淘汰不再被访问的数据,保证缓存中的数据贴近当前热点。 相比之下,LFU 更关注历史访问频次,容易保留已经失去时效性的旧热点,因此不作为首选。
-
-
Redis的内存用完了会发生什么?
主要看数据淘汰策略是什么?如果是默认的配置(noeviction),会直接报错
总结:
1.Redis提供了8种不同的数据淘汰策略,默认是noeviction不删除任何数据,内存不足直接报错
2.LRU:最少最近使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
3.LFU:最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高
平时开发过程中用的比较多的就是allkeys-Iru(结合自己的业务场景)
#数据人的面试交流地##找工作的破防时刻##牛客解忧铺##我的求职进度条#
