Redis持久化机制

孤者浪人 提交于 2020-02-27 03:59:43

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快照文件。

快照原理

执行快照时的过程如下:

  1. Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);
  2. 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件;
  3. 当子进程写完所有数据后会用该临时文件替换旧的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:交给操作系统同步;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!