众所周知,Redis是内存数据库,也就是把数据存在内存上,读写速度很快,但是,内存的数据容易丢失,为了数据的持久性,还得把数据存储到硬盘上
也就是说,内存有一份数据,硬盘也应该有一份数据,而且两份数据应该是相同的
也就是说硬盘上的数据应该是内存上数据的备份。
Redis给我们提供了两种策略来实现数据的持久化,RDB和AOF
RDB
RDB定期的把Redis内存中的所有数据,都写到硬盘上,生成一个“快照”,这个快照,本质上就是一个.rdb后缀的文件
.rdb的位置在redis.conf配置里设置
配置文件位置:
设置的工作目录
查看工作目录
生成快照时机
手动触发
通过redis客户端,执行特定的命令,来触发快照生成
1)save
save命令会阻塞其他客户端的命令,一般不建议使用,在高并发场景下容易挂掉
2)bgsave
用fork创建子进程的方式,来完成并发编程,让子进程去生成快照
如果多个客户端同时bgsave,也只会生成一个子进程
fork命令创建子进程,子进程复制父进程的内存、文件描述符等,但是是写时拷贝,父子进程共享相同的物理内存页,在内存没有改变的时候,指向的同一块内存地址空间,省去复制的开销
自动触发
在redis配置文件中设置,让redis自动每隔多长时间/产生多少次修改 就触发生成快照
这表示
- 每900秒(15分钟)如果有至少1次写操作,则触发RDB快照。
- 每300秒(5分钟)如果有至少10次写操作,则触发RDB快照。
- 每60秒如果有至少10000次写操作,则触发RDB快照。
- (如果设置为 save "")表示关闭自动生成快照
当生成rdb镜像操作的时候,先把要生成的快照数据保存到一个临时文件中,当快照生成完毕之后,再把原来的rdb文件删掉,把新文件改名为刚才的文件名(dump.rdb)
从始至终,rdb文件都只有一个
rdb文件损坏
一般不要手动去修改rdb文件,会出现不可预知的问题。
丢失数据外,还可能因为读取数据失败而启动redis服务器失败
如果redis服务器挂了,可以看看redis的日志,看看发生了啥
(这个路径也是在配置文件中设置的)
打开日志文件后,发现
表示在恢复数据的时候没读完,意外读到了EOF文件结束符
这时候,可以通过redis提供的rdb文件的检查工具,检查问题
redis-check-rdb dump.rdb命令不会真的启动服务器,而是以检查工具的方式运行
发现了问题所在
AOF
AOF通过将每个写操作记录到日志文件来实现持久化
AOF默认是关闭状态
可以在Redis配置文件(redis.conf)中进行配置
# 启用AOF
appendonly yes# 设置AOF文件名称
appendfilename "appendonly.aof"# 设置AOF同步策略
appendfsync everysec# 启用AOF重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
AOF工作流程
AOF不会影响Redis对请求的处理速度
AOF会把写操作写入内存中的EAOF缓冲区,积累一波后,再统一刷盘到硬盘
刷盘时机
在Redis配置文件(redis.conf)中可以进行配置
# 设置AOF同步策略
appendfsync everysec
appendfsync always
线程调用 write
执行写操作后,后台线程( aof_fsync
线程)立即会调用 fsync
函数同步 AOF 文件(刷盘),fsync
完成后线程返回,这样会严重降低 Redis 的性能(write
+ fsync
)
appendfsync everysec
主线程调用 write
执行写操作后立即返回,由后台线程( aof_fsync
线程)每秒钟调用 fsync
函数(系统调用)同步一次 AOF 文件(write
+fsync
,fsync
间隔为 1 秒)
appendfsync no
主线程调用 write
执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30 秒一次(write
但不fsync
,fsync
的时机由操作系统决定)
重写机制
当 AOF 变得太大时,Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。
重写原理
如果某个键经历了多次更新操作,AOF文件中会有多条命令记录该键的变化。
例如set key 111;set key 222; set key 333 这里对key执行了多次更新操作,但对于现在来说,只有最后的更新有意义,所以只需要保存最后一次更新就好
重写流程
-
1.触发重写: AOF重写可以由用户手动触发(通过 bgrewriteaof 命令)或根据配置自动触发。自动触发通常基于两个条件:
- AOF文件的大小增长到上次重写后的两倍。
- AOF文件的大小超过指定的最小值。
可以在配置文件中设置自动触发
# 启用AOF重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
- auto-aof-rewrite-percentage 100 : 执行 AOF 重写时,当前 AOF 大小(aof_current_size)和上一次重写时 AOF 大小(aof_base_size)的比值。如果当前 AOF 文件大小增加了这个百分比值,将触发 AOF 重写。将此值设置为 0 将禁用自动 AOF 重写。默认值为 100。
- auto-aof-rewrite-min-size 64mb:如果 AOF 文件大小小于该值,则不会触发 AOF 重写。默认值为 64 MB;
-
2.创建子进程: Redis会fork一个子进程来执行AOF重写操作。子进程会创建一个新的AOF文件,并将当前的数据集以Redis命令的形式写入该文件。
-
3.记录重写期间的写操作: 当子进程在进行AOF重写时,主进程仍然在处理新的写操作。这些新的写操作会被记录到重写缓冲区(rewrite buffer)中。
-
4.完成重写并同步数据: 当子进程完成新的AOF文件写入后,它会通知主进程。主进程会将重写缓冲区中的数据同步到新的AOF文件中,以确保所有写操作都被记录。
-
5.替换旧的AOF文件: 一旦新AOF文件完成并同步所有数据,Redis会用新的AOF文件替换旧的AOF文件。
校验机制
AOF 校验机制是 Redis 在启动时对 AOF 文件进行检查,以判断文件是否完整,是否有损坏或者丢失的数据。这个机制的原理其实非常简单,就是通过使用一种叫做 校验和(checksum) 的数字来验证 AOF 文件。这个校验和是通过对整个 AOF 文件内容进行 CRC64 算法计算得出的数字。如果文件内容发生了变化,那么校验和也会随之改变。因此,Redis 在启动时会比较计算出的校验和与文件末尾保存的校验和(计算的时候会把最后一行保存校验和的内容给忽略点),从而判断 AOF 文件是否完整。如果发现文件有问题,Redis 就会拒绝启动并提供相应的错误信息。AOF 校验机制十分简单有效,可以提高 Redis 数据的可靠性。