说明:Redis是一个内存数据库,数据保存在内存中,但是我们都知道内存的数据变化是很快的,也容易发生丢失。所以Redis提供了持久化的机制,分别是RDB(Redis DataBase)和AOF(Append Only File)。
Redis持久化的两种方式:RDB、AOF以及持久化方式的选择
一、RDB(Redis DataBase)
RDB持久化方式是通过快照(snapshotting)完成的,redis会自动将内存中所有数据以二进制方式生成一份副本并存储在硬盘上。当redis重启时,并且AOF持久化未开启时,redis会读取RDB持久化生成的二进制文件并加载到内存里(默认文件名称dump.rdb,可通过设置dbfilename修改)进行数据恢复,对于持久化信息可以用过命令“info Persistence”查看。
127.0.0.1:6379> config get dbfilename //查看备份文件名,此名称是默认的,redis.conf中有说明
1) "dbfilename"
2) "dump.rdb"
127.0.0.1:6379> config get dir //查看备份的目录名,可以通过config set dir 'path'进行手动设置
1) "dir"
2) "/usr/local/bin"
127.0.0.1:6379>
127.0.0.1:6379> info Persistence //查看备份信息
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1605412450 //最后一次持久化的时间
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:-1
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:0
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0
module_fork_in_progress:0
module_fork_last_cow_size:0
127.0.0.1:6379>
RDB快照触发条件
RDB生成快照可自动促发,也可以使用命令手动触发,以下是redis触发执行快照条件:
-
客户端执行命令 save 和 bgsave 会生成快照;
127.0.0.1:6379> save //客户端执行save命令,该命令强制redis执行快照,这时候redis处于阻塞状态,不会响应任何其他客户端发来的请求,直到RDB快照文件执行完毕,所以请慎用
OK
127.0.0.1:6379> bgsave //Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。可以通过 lastsave 命令获取最后一次成功执行快照的时间
Background saving started
127.0.0.1:6379>
-
根据配置文件 save m n 规则进行自动快照;
save m n规则说明:在指定的m秒内,redis中有n个键发生改变,则自动触发bgsave。该规则默认也在redis.conf中进行了配置,并且可组合使用,满足其中一个规则,则触发bgsave。
-
主从复制时,从库全量复制同步主库数据,此时主库会执行 bgsave 命令进行快照;
在redis主从复制中,从节点执行全量复制操作,主节点会执行bgsave命令,并将rdb文件发送给从节点。
-
客户端执行数据库清空命令 flushall 时候,触发快照;
flushall命令用于清空数据库,请慎用,当我们使用了则表明我们需要对数据进行清空,那redis当然需要对快照文件也进行清空,所以会触发bgsave。
127.0.0.1:6379> flushall //执行flushall命令,也会产生dump.rdb文件,但里面是空的,无意义
OK
127.0.0.1:6379>
-
客户端执行 shutdown 关闭redis时,触发快照;
shutdown命令,redis在关闭前处于安全角度将所有数据全部保存下来,以便下次启动会恢复。
-
可以 cp dump.rdb dump_new.rdb 冷拷贝后重新使用,到时候只需要将 dump_new.rdb 改为 dump.rdb 然后重新启动redis则自动加载到内存里;
RDB持久化配置
save m n #配置快照(rdb)促发规则,格式:save <seconds> <changes> #save 900 1 900秒内至少有1个key被改变则做一次快照 #save 300 10 300秒内至少有300个key被改变则做一次快照 #save 60 10000 60秒内至少有10000个key被改变则做一次快照 #关闭该规则使用svae “” dbfilename dump.rdb #rdb持久化存储数据库文件名,默认为dump.rdb stop-write-on-bgsave-error yes #yes代表当使用bgsave命令持久化出错时候停止写RDB快照文件,no表明忽略错误继续写文件。 rdbchecksum yes #在写入文件和读取文件时是否开启rdb文件检查,检查是否有无损坏,如果在启动是检查发现损坏,则停止启动。 dir "/etc/redis" #数据文件存放目录,rdb快照文件和aof文件都会存放至该目录,请确保有写权限 rdbcompression yes #是否开启RDB文件压缩,该功能可以节约磁盘空间
RDB优点:
适合大规模的数据恢复。如果业务对数据完整性和一致性要求不高,RDB是很好的选择。
RDB缺点:
-
数据的完整性和一致性不高,因为RDB可能在最后一次备份时宕机了。
-
备份时占用内存,因为Redis 在备份时会独立创建一个子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍哦),最后再将临时文件替换之前的备份文件。所以要考虑到大概两倍的数据膨胀性。
二、AOF(Append Only File)
以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件(默认文件名:appendonly.aof)但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
注意:当 dump.rdb 和 appendonly.aof 两个文件同时存在时,则默认加载 appendonly.aof 文件
开启AOF
redis默认是关闭了AOF持久化,开启AOF通过配置 appendonly 为 yes 开启,我们修改配置文件或者在命令行直接使用 config set 修改,在用 config rewrite 同步到配置文件。通过客户端修改好处是不用重启redis,AOF持久化直接生效。
127.0.0.1:6379> config get appendfilename //查看默认文件名
1) "appendfilename"
2) "appendonly.aof"
127.0.0.1:6379>
127.0.0.1:6379> config get appendonly //查看appendonly状态
1) "appendonly"
2) "no"
127.0.0.1:6379> config set appendonly yes //社会组appendonly状态
OK
127.0.0.1:6379> config get appendonly //再次查看appendonly状态
1) "appendonly"
2) "yes"
127.0.0.1:6379> config rewrite //把appendonly状态写入配置文件
OK
127.0.0.1:6379>
修复 appendonly.aof 文件
说明:当aof由于各种不当操作造成无法加载时,则使用指令:
[root@centos102 bin]# ll total 38084 -rw-r--r--. 1 root root 169 Nov 15 13:38 appendonly.aof -rw-r--r--. 1 root root 125 Nov 15 13:38 dump.rdb -rwxr-xr-x. 1 root root 4741000 Nov 9 01:11 redis-benchmark -rwxr-xr-x. 1 root root 9724328 Nov 9 01:11 redis-check-aof -rwxr-xr-x. 1 root root 9724328 Nov 9 01:11 redis-check-rdb -rwxr-xr-x. 1 root root 5061344 Nov 9 01:11 redis-cli lrwxrwxrwx. 1 root root 12 Nov 9 01:11 redis-sentinel -> redis-server -rwxr-xr-x. 1 root root 9724328 Nov 9 01:11 redis-server [root@centos102 bin]# redis-check-aof --fix appendonly.aof //修复 appendonly.aof 文件 0x 8b: Expected prefix '*', got: 'i' AOF analyzed: size=169, ok_up_to=139, diff=30 This will shrink the AOF from 169 bytes, with 30 bytes, to 139 bytes Continue? [y/N]: y Successfully truncated AOF [root@centos102 bin]#
AOF配置参数
auto-aof-rewrite-min-size 64mb #AOF文件最小重写大小,只有当AOF文件大小大于该值时候才可能重写,4.0默认配置64mb。 #这里所说的重写指的是重写appnedonly.aof这个文件。 auto-aof-rewrite-percentage 100 #当前AOF文件大小和最后一次重写后的大小之间的比率等于或者等于指定的增长百分比,如100代表当前AOF文件是上次重写的两倍时候才重写。 #这里所说的重写指的是重写appnedonly.aof这个文件。 #以上两条是重写的策略,也可以手动触发重写;重写之后发现appnedonly.aof文件被清空了。
127.0.0.1:6379> BGREWRITEAOF //手动触发重写命令 Background append only file rewriting started 127.0.0.1:6379>
appendfsync everysec #no:不使用fsync方法同步,而是交给操作系统write函数去执行同步操作,在linux操作系统中大约每30秒刷一次缓冲。这种情况下,缓冲区数据同步不可控,并且在大量的写操作下,aof_buf缓冲区会堆积会越来越严重,一旦redis出现故障,数据 #always:表示每次有写操作都调用fsync方法强制内核将数据写入到aof文件。这种情况下由于每次写命令都写到了文件中, 虽然数据比较安全,但是因为每次写操作都会同步到AOF文件中,所以在性能上会有影响,同时由于频繁的IO操作,硬盘的使用寿命会降低。 #everysec:数据将使用调用操作系统write写入文件,并使用fsync每秒一次从内核刷新到磁盘。 这是折中的方案,兼顾性能和数据安全,所以redis默认推荐使用该配置。 aof-load-truncated yes #当redis突然运行崩溃时,会出现aof文件被截断的情况,Redis可以在发生这种情况时退出并加载错误,以下选项控制此行为。 #如果aof-load-truncated设置为yes,则加载截断的AOF文件,Redis服务器启动发出日志以通知用户该事件。 #如果该选项设置为no,则服务将中止并显示错误并停止启动。当该选项设置为no时,用户需要在重启之前使用“redis-check-aof”实用程序修复AOF文件在进行启动。 appendonly no #yes开启AOF,no关闭AOF appendfilename appendonly.aof #指定AOF文件名,4.0无法通过config set 设置,只能通过修改配置文件设置。 dir /etc/redis #RDB文件和AOF文件存放目录
AOF优点:
(1)AOF可以更好的保护数据不丢失,一般AOF会以每隔1秒,通过后台的一个线程去执行一次fsync操作,如果redis进程挂掉,最多丢失1秒的数据。
每修改同步:appendfsync always 同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好。
每秒同步:appendfsync everysec 异步操作,每秒记录 如果一秒内宕机,有数据丢失。
不同步:appendfsync no 从不同步。
(2)AOF以appen-only的模式写入,所以没有任何磁盘寻址的开销,写入性能非常高。
(3)AOF日志文件的命令通过非常可读的方式进行记录,这个非常适合做灾难性的误删除紧急恢复,如果某人不小心用 flushall 命令清空了所有数据,只要这个时候还没有执行rewrite,那么就可以将日志文件中的flushall删除,进行恢复。
AOF缺点:
(1)对于同一份文件AOF文件比RDB数据快照要大,恢复速度慢于rdb。
(2)AOF运行效率要慢于RDB,每秒同步策略效率较好,不同步效率和RDB相同。
三、RDB、AOF持久化方式选择
RDB持久化方式能够在指定的时间间隔对数据进行快照存储。
AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始数据,AOF命令以redis协议追加保存每次写的操作到文件末尾。
Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。
只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。
同时开启两种持久化方式:
在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢?
建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。
四、性能建议:
因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。
如果Enalbe AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。默认超过原大小100%大小时重写可以改到适当的数值。
如果不Enable AOF ,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。