RDB存储
RDB方式的持久化是通过快照完成的,当符合一定条件时Redis会自动将内存中的所有数据生成一份副本并存储在硬盘上。
Redis会在一下集中情况下对数据进行快照:
- 根据配置规则进行快照;
- 用户执行SAVE或BGSAVE命令;
- 执行FLUSHALL命令;
- 执行复制时;
根据配置规则进行快照
# 时间策略
save 900 1
save 300 10
save 60 10000
# 文件名称
dbfilename dump.rdb
# 文件保存路径
dir /home/work/app/redis/data/
# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes
# 是否压缩
rdbcompression yes
# 导入时是否检查
rdbchecksum yes
例如Redis的配置文件中:
# 时间策略
save 900 1
save 300 10
save 60 10000
如果符合其中的任意一条,则会触发一次快照。
当然如果你想要禁用RDB配置,也是非常容易的,只需要在save的最后一行写上:save ""
SAVE或BGSAVE
当执行SAVE时,Redis会同步进行快照操作,快照执行过程中会阻塞所有来自客户端的请求。
当执行BGSAVE时,可以在后台异步进行快照操作,快照的同时服务器还可以继续响应来自客户端的请求。如果想知道快照是否完成,可以通过LASTSAVE命令获取最近一次成功执行快照的时间。
FLUSHALL
执行FLUSHALL命令时,Redis会清除数据库中的所有数据,只要自动快照条件不为空,Redis就会执行一次快照操作。
执行赋值
当设置了主从模式,Redis会在复制初始化时进行自动快照,即使没有定义自动快照条件,也会生成RDB快照文件。
快照原理
执行快照时的过程如下:
- Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);
- 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件;
- 当子进程写完所有数据后会用该临时文件替换旧的RDB文件;
类Unix操作系统在执行fork的时候会使用写时复制策略,即fork函数发生那一刻父子进程共享同一内存数据,当父进程要更改其中某片数据时,操作系统会将该片数据复制一份以保证子进程不受影响,所以新RDB文件存储的时fork那一刻的内存数据。
采用写时复制策略,要确保操作系统允许应用程序申请超过可用内存(物理内存和交换分区)的空间,方法是在/etc/sysctl.conf文件中加入vm.overcommit_memory=1,然后重启或者执行sysctl vm.overcommit_memory=1确保设置生效。
所以如果进行快照的过程中,写入操作较多,造成fork前后数据差异较大,是会使内存使用量显著超过实际数据大小,进行内存用量估算时不要忽略。
Redis启动后会读取RDB文件,将数据从硬盘加载到内存,通常将1000万个字符串、大小为1GB的快照文件加载到内存需要花费20~30秒。
AOF存储
AOF可以将Redis执行的每一条写命令追加到磁盘文件中,这一过程会降低Redis的性能。
根据配置进行AOF文件重写
# 是否开启aof
appendonly yes
# 文件名称
appendfilename "appendonly.aof"
# 同步方式
appendfsync everysec
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加载aof时如果有错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
随着保存的写命令越来越多,Redis检测到达一定条件时,就会从写AOF文件:
# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
上面参数的意思是,目前的AOF文件大小超过上一次重写时AOF文件的大小(100%)时,会重写,如果之前没有重写过,那么在文件大小为64MB时,进行第一次重写。
同步硬盘数据
由于操作系统缓存机制,数据并没有真正写入硬盘,而是进入了硬盘缓存。默认情况下,操作系统30秒会执行一次同步操作去真正的写入。这30秒种操作系统发生异常则会导致硬盘缓存中的数据丢失,如果无法容忍这种情况发生:
appendfsync everysec
#appendfsync always
#appendfsync no
可以设置appendfsync参数:
- everysec:每秒写入一次;
- always:每次执行写入都会同步;
- no:交给操作系统同步;
来源:oschina
链接:https://my.oschina.net/u/2450666/blog/3160162