前言
我们都知道,redis是基于内存存储的,如果redis因为异常导致进程结束,那么我们的数据就会丢失,为了解决这个问题,redis提供了2种持久化方式,默认为 rdb 方式
RDB方式
RDB的持久化方式是通过快照方式进行的,当符合一定的条件时,redis会把当前内存中的数据做一个副本,然后持久化到磁盘上,这个过程称为快照,redis会在下列情况下进行快照
- 根据配置规则自动快照
- 用户执行save或者bgsave命令
- 用户执行flushall命令
- 从节点执行复制时
根据配置规则自动快照
redis允许用户自定义快照时间,当符合条件时,redis会自动进行快照,执行快照的文件可以在redis.conf里配置,配置规则为 save 时间 m 异动数据 n
比如 save 900 1 指的是在 15 分钟内如果有1条数据产生变动 则产生一个快照
可以换行添加多个条件, 条件之间为 或 的关系
用户执行save 或者 bgsave 的命令时
- save命令
save命令执行时,redis会同步的进行操作,此时会阻塞所有客户端请求,造成客户端响应时间时间不响应,或者响应时间变长,所以尽量避免在生产环境种使用该命令 - bgsave命令
需要手动执行快照命令时,推荐使用bgsave命令,bgsave命令会在后台异步的进行快照操作,但是客户端还可以继续响应请求,但是此处有一个问题是,redis实现快照是fork一个子进程去执行,如果是在linux系统下,子进程刚创建的时候,和父进程共享内存空间,只有父进程内存空间内的数据发生变化时,子进程才分配一块自己的空间,这种机制被称为 写时复制 , 在这种机制下,fork 一个子进程去执行快照操作不会占用双倍的内存,但是如果fork时父进程产生了大量的修改或者写入操作,那么子进程的内存页就需要重新分配,就会产生较大的内存占用,因此此处要注意
用户执行flushall命令时
当flushall命令执行时,如果用户配置了快照规则,无论是否达到条件都会执行一次快照的操作,如果用户没有配置快照条件,则执行 flushall 不会执行快照的操作
执行复制时
当用户配置了主从模式,当复制操作初始化时,则会对当前内存数据执行一次快照操作
快照原理
redis的快照是如何实现的呢?redis默认会把当前快照文件存储在默认目录种的 dump.rdb中,可以通过配置dir 和 dbfilename 两个参数来对快照的目录和快照的名字进行修改,快照的执行步骤如下
- 1 redis 复制一份当前进程的副本,子进程
- 2 主进程继续接收客户端请求
- 3 子进程写入完数据后,会用临时文件替换调就的rdb文件
AOF模式
当redis存储非临时数据时,一般需要打开 AOF 模式,AOF 的工作原理是,执行每一条命令都序列化到磁盘上,来防止进程终止造成的数据丢失,这显然会对redis的性能产生一定的影响,但是这个影响大部分情况下可以接受的,可以采用较快的硬盘来提高aof的性能
- 如何开启aof
appendonly yes
开启aof之后每一条命令都会写入到磁盘的aof文件,aof文件的保存位置与rdb相同,都是通过dir配置的,默认的文件名称为 appendonly.aof 也可以通过 appendfilename 去修改 - aof亢余命令优化
因为aof文件会记录没一条命令 比如 set a 1 set a 2 这两条命令,很明显的就是第二条覆盖了第一条,但是aof会记录2条,所以会有很多无用命令,浪费大量磁盘空间,实际上redis解决了这个问题,每当达到一定条件时,redis会自动重写aof文件,redis提供了如下配置
1 auto-aof-rewirite-percentage 100
2 auto-aof-rewirite-min-size 64mb
auto-aof-rewirite-percentage设置当前文件大小超过上一次重写aof文件的 百分比 会自动触发重写机制,auto-aof-rewirite-min-size是限制了aof文件的最小重写大小,比如小于 64mb 就不对aof重写 - 同步硬盘数据
虽然每次操作都记录在了aof文件里,但是操作系统并不会实时的把数据刷新到磁盘,默认是30秒进行一次刷新操作,如果此时系统异常退出,会导致丢失一部分数据,这是生产环境中无法忍受的,所以redis提供了如下配置,保证每次操作都同步到磁盘中。
appendfsync 【always、everysec、no】
always 代表每次操作都执行同步,这是最慢的一种模式,也是最安全的一种模式
everysec 代表每秒执行一次同步操作
no 代表完全由操作系统来保证同步操作