RDB快照(Redis DataBase)
RDB是一种快照存储持久化方式,具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中,默认保存的文件名为dump.rdb,而在Redis服务器启动时,会从新加载dump.rdb文件的数据到内存当中恢复数据。redis
开启RDB持久化方式
开启RDB持久化方式很简单,客户端能够经过向Redis服务器发送save或bgsave命令让服务器生成rdb文件,或者经过服务器配置文件指定触发RDB条件。每次执行都会将全部redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。安全
方式一:save命令服务器
# 同步数据到磁盘上 > save
当客户端向服务器发送save命令请求进行持久化时,服务器会阻塞save命令以后的其余客户端的请求,直到数据同步完成。 若是数据量太大,同步数据会执行好久,而这期间Redis服务器也没法接收其余请求,因此,最好不要在生产环境使用save命令。app
方式二:bgsave命令异步
# 异步保存数据集到磁盘上 > bgsave
- 当客户端发服务发出bgsave命令时,Redis服务器主进程会forks一个子进程来解决数据同步问题,在将数据保存到rdb文件以后,子进程会退出。
- 因此,与save命令相比,Redis服务器在处理bgsave采用子线程进行IO写入,而主进程仍然能够接收其余请求,但forks子进程是同步的,因此forks子进程时,同样不能接收其余请求,这意味着,若是forks一个子进程花费的时间过久(通常是很快的),bgsave命令仍然有阻塞其余客户的请求的状况发生。
- 咱们能够控制单个Redis实例的最大内存,来尽量下降Redis在fork时的事件消耗。以及上面提到的自动触发的频率减小fork次数,或者使用手动触发,根据本身的机制来完成持久化。
方式三:经过配置文件自动触发性能
自动触发的场景主要是有如下几点:url
- 1.根据咱们的 save m n 配置规则自动触发;
- 2.从节点全量复制时,主节点发送rdb文件给从节点完成复制操做,主节点会触发 bgsave;
- 3.执行 debug reload 时;
- 4.执行shutdown时,若是没有开启aof,也会触发。
这里咱们讲的是根据配置文件自动触发:spa
# 时间策略 #关闭RDB只须要将全部的save保存策略注释掉便可 save 900 1 #900s内若是有1条数据写入,就产生RDB快照 save 300 10 #300s内有10条数据写入,就产生RDB快照 save 60 10000 #60s内若是有10000条数据写入,就产生RDB快照 # 文件名称 dbfilename dump.rdb # 文件保存路径 dir /var/lib/redis/6379 # 若是持久化出错,主进程是否中止写入 stop-writes-on-bgsave-error yes # 是否压缩 # 建议没有必要开启,毕竟Redis自己就属于CPU密集型服务器,再开启压缩会带来更多的CPU消耗,相比硬盘成本,CPU更值钱。 rdbcompression no # 导入时是否检查 rdbchecksum yes
save和bgsave对比
配置文件自动生成rdb文件后台使用的是bgsave方式。操作系统
RDB文件
前面介绍了三种让服务器生成rdb文件的方式,不管是由主进程生成仍是子进程来生成,其过程以下:.net
- 生成临时rdb文件,并写入数据。
- 完成数据写入,用临时文件替代正式rdb文件。
- 删除原来的db文件。
COW写时复制(copy-on-write)
fork建立出的子进程,与父进程共享内存空间。也就是说,若是子进程不对内存空间进行写入操做的话(Redis的子进程只作数据落盘的操做,也不会去写数据),内存空间中的数据并不会复制给子进程,这样建立子进程的速度就很快了!(不用复制,直接引用父进程的物理空间,玩的是指针)。
当Redis父进程修改数据时,父进程会将原先的数据复制一份生成新的副本,而后修改父进程的指针,指向新的数据,此时父进程修改的新的数据不会影响到子进程。此时子进程的指针仍然指向旧的数据,子进程看到的数据仍是bgsave时候的数据。当下一次执行bgsave时,新fork出来的子进程指针才会指向此次新的数据。
AOF(append-only file)
与RDB存储某个时刻的快照不一样,AOF持久化方式会记录客户端对服务器的每一次写操做命令,并将这些写操做以追加的方式保存到之后缀为aof文件中,在Redis服务器重启时,会加载并运行aof文件的命令,以达到恢复数据的目的。
开启AOF持久化的方式
方式一:bgrewriteaof命令
> bgrewriteaof
方式二:经过配置文件自动触发
Redis默认不开启AOF持久化方式,咱们能够在配置文件中开启并进行更加详细的配置:
#开启aof appendonly yes # 文件名称 appendfilename "appendonly.aof" # 同步方式 #appendfsync always #每次有新命令追加到 AOF 文件时就执行一次 fsync ,很是慢,也很是安全。 appendfsync everysec #默认方式,每秒 fsync 一次,足够快,而且在故障时只会丢失 1 秒钟的数据。 #appendfsync no #从不 fsync ,将数据交给操做系统来处理。更快,也更不安全的选择。
重写
AOF将客户端的每个写操做都追加到aof文件末尾,好比对一个key屡次执行incr命令,这时候,aof保存每一次命令到aof文件中,aof文件会变得很是大。
127.0.0.1:6379> INCR readcount (integer) 1 127.0.0.1:6379> INCR readcount (integer) 2 127.0.0.1:6379> INCR readcount (integer) 3 127.0.0.1:6379> INCR readcount (integer) 4 127.0.0.1:6379> INCR readcount (integer) 5
这是一种resp协议格式数据,星号后面的数字表明命令有多少个参数,$号后面的数字表明这个参数有几个字符
[root@redis 6379]# cat appendonly.aof *2 $6 SELECT $1 0 *2 $4 INCR $9 readcount *2 $4 INCR $9 readcount *2 $4 INCR $9 readcount *2 $4 INCR $9 readcount *2 $4 INCR $9 readcount
手动执行重写命令BGREWRITEAOF:
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
重写后AOF文件里以下,将多个incr命令进行了合并:
[root@redis 6379]# cat appendonly.aof *2 $6 SELECT $1 0 *3 $3 SET $9 readcount $1 5
重写配置参数
AOF重写redis会fork出一个子进程去作(与bgsave命令相似),不会对redis正常命令处理有太多影响:
auto‐aof‐rewrite‐min‐size 64mb #aof文件至少要达到64M才会自动重写,文件过小恢复速度原本就 很快,重写的意义不大 auto‐aof‐rewrite‐percentage 100 #aof文件自上一次重写后文件大小增加了100%则再次触发重写,例如上一次重写的大小是64M,那么下一次达到128M再作重写
AOF重写流程图
- 在重写期间,因为主进程依然在响应命令,为了保证最终备份的完整性;所以它依然会写入旧的AOF file中,若是重写失败,可以保证数据不丢失。
- 为了把重写期间响应的写入信息也写入到新的文件中,所以也会为子进程保留一个buf,防止新写的file丢失数据。
- 重写是直接把当前内存的数据生成对应命令,并不须要读取老的AOF文件进行分析、命令合并。
- 不论是RDB仍是AOF都是先写入一个临时文件,而后经过 rename 完成文件的替换工做。
混合持久化
重启 Redis 时,咱们不多使用 RDB来恢复内存状态,由于会丢失大量数据。咱们一般使用 AOF 日志重放,可是重放 AOF 日志性能相对 RDB来讲要慢不少,这样在 Redis 实例很大的状况下,启动须要花费很长的时间。Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。经过以下配置能够开启混合持久化(前提必须先开启aof):
aof‐use‐rdb‐preambleyes #开启混合持久化
若是开启了混合持久化,AOF在重写时,再也不是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻以前的内存作RDB快照处理,而且将RDB快照内容和增量的AOF修改内存数据的命令存在一块儿,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行更名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。因而在 Redis 重启的时候,能够先加载 RDB 的内容,而后再重放增量 AOF 日志就能够彻底替代以前的 AOF 全量文件重放,所以重启效率大幅获得提高。
127.0.0.1:6379> set k 1 OK 127.0.0.1:6379> set k 2 OK 127.0.0.1:6379> BGREWRITEAOF Background append only file rewriting started
查看此时的appendonly.aof文件:此时存放的是RDB的内容
[root@redis 6379]# cat appendonly.aof REDIS0009� redis-ver5.0.7� �edis-bits�@�ctime�%y�_used-mem�� aof-preamble���k� readcount�� R��i9$�[root@redis 6379]#
若是新增长了数据:
127.0.0.1:6379> set k 3 OK
那么新的数据会觉得RESP命令的方式追加在后面:
[root@redis 6379]# cat appendonly.aof REDIS0009� redis-ver5.0.7� �edis-bits�@�ctime�%y�_used-mem�� aof-preamble���k� readcount�� R��i9$�*2 $6 SELECT $1 0 *3 $3 set $1 k $1 3
混合持久化AOF文件结构以下:
从持久化中恢复数据
数据的备份、持久化作完了,咱们如何从这些持久化文件中恢复数据呢?若是一台服务器上有既有RDB文件,又有AOF文件,该加载谁呢?
其实想要从这些文件中恢复数据,只须要从新启动Redis便可。咱们仍是经过图来了解这个流程:
启动时会先检查AOF文件是否存在,若是不存在就尝试加载RDB。那么为何会优先加载AOF呢?由于AOF保存的数据更完整,经过上面的分析咱们知道AOF基本上最多损失1s的数据。
RBD和AOF对比
另外RBD不支持拉链,只有一个dump.rdb文件。