持久化
持久化顾名思义就是将内存中的数据写入硬盘中。
Redis提供了两种不同的持久化方法来将数据存储到硬盘中:RDB、AOF。
这两种持久化方案既可以同时使用,又可以单独使用。甚至都不使用。具体根据应用和用户数据来决定。
RDB
RDB也称为快照。将某一时刻,Redis内存中的所有数据都写入硬盘中。
从Redis根目录中的redis.conf文件中,我们可以看到详细的配置及说明。
配置项
-
save 900 1
Will save the DB if both the given number of seconds and the given number of write operations against the DB occurred.
在给定的时间秒数内进行了给定次数的操作,将进行保存(save 900 1 :在15分钟内,至少执行了一次写入操作,redis会自动开始一次新的BGSAVE操作)。
我们可以注释掉save来禁用。
-
stop-writes-on-bgsave-error yes
在后台处理保存数据出错时停止写入。
-
rdbcompression yes
rdb数据文件压缩
-
rdbchecksum yes
rdb文件校验。使用的是CRC64。
在禁用校验和的情况下创建的RDB文件的校验和为零,这将指示加载代码跳过该校验。
-
dbfilename dump.rdb
rdb文件名称
配置:
# 秒数,操作数自定义
save 900 1
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
# 路径自定义 数据文件路径
dir ./
补充:
-
创建快照的方法有:
- 客户端向Redis发送
SAVE
命令 - 客户端向Redis发送
BGSAVE
命令 - 用户在配置文件中设置了save配置项,在该条件下触发
- 当Redis收到
SHUTDOWN
关闭请求时,或收到标准TERM信号时。会执行SAVE
命令 - 当Redis服务器收到了另一台Redis服务器的
SYNC
命令开始复制操作时,如果主服务器当前没有执行BGSAVE
命令,或主服务并非刚刚执行完BGSAVE
操作,那么主服务器会执行BGSAVE
命令
- 客户端向Redis发送
-
SAVE
与BGSAVE
-
SAVE
收到
SAVE
命令,Redis在进行RDB持久化完成之前,不再响应其他任何命令。 -
BGSAVE
Redis会创建一个子进程。子进程进行快照,父进程继续处理命令请求。
SAVE
命令并不常用,通常在没有足够内存去执行BGSAVE
命令,又或即使等待RDB持久化执行完毕也无所谓的情况下,才使用。但是随着Redis占用的内存越来越多,
BGSAVE
命令创建子进程消耗的时间也会越来越多。如果Redis内存占用达到了10个GB,剩余空闲内存不足时,或Redis运行在虚拟机上时,执行BGSAVE
命令可能会导致系统长时间停顿。BGSAVE
命令执行而导致的停顿时间有多长取决于Redis所在的系统:对于真实系统、VMWare、KVM,Redis进程每占用一个GB内存,创建该进程的子进程所需时间要增加10-20毫秒;对于Xen虚拟机则增加200-300毫秒。为了防止Redis创建子进程出现停顿,可以考虑关闭自动保存。通过手动发送
SAVE
或BGSAVE
命令触发。手动发送BGSAVE
可以控制卡顿出现的时间节点;手动发送SAVE
命令除了可以控制阻塞的时间节点外,无需创建子进程进行资源抢夺,速度要比BGSAVE
快。 -
总结
在只使用RDB(快照)进行持久化时,如果系统崩溃,用户将丢失最近一次快照之后更改的所有数据。
因此RDB只适用于丢失一部分数据也不会造成问题的应用程序。
对于大多数应用,丢失长时间的数据是不可能接受的,则可以使用AOF。
AOF
append-only file。在Redis执行写命令时,将执行的写命令复制到硬盘中。即AOF持久化将被执行的写命令写到AOF文件末尾,记录数据发生的变化。因此Redis只要从头到尾执行AOF文件中的所有写命令,即可恢复数据。
配置项
-
appendonly yes
开启AOF
-
appendfilename appendonly.aof
aof文件名
-
appendfsync everysec
进行持久化的方式
everysec:每秒执行一次,默认(可能会丢一秒的数据);
always:实时,IO开销较大,较慢,但不丢失数据;
no:只要让系统在需要时操作(让操作系统来决定在何时同步)。
-
no-appendfsync-on-rewrite no
重写过程中是否向aof文件写入。
-
auto-aof-rewrite-percentage 100
触发重写文件增长百分比,默认100
-
auto-aof-rewrite-min-size 64mb
触发重写最小文件大小。即aof文件超过64M,触发重写。
appendonly yes
appendfilename appendonly.aof
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 路径自定义 数据文件路径
dir ./
警告:
使用固态硬盘的需要谨慎使用appendfsync always
,Redis每次只写入一个命令,不断的写入少量数据可能会引发写入放大问题,影响固态硬盘寿命。
补充:
-
appendfsync
的三个选项-
always
每个Redis写命令都被写入硬盘,将数据丢失的概率减到最小,但是受硬盘性能的限制。
机械硬盘大约200个每秒,SSD大约几万个每秒。
-
everysec
兼顾了写入性能和数据安全,Redis每秒同步一次AOF文件时的性能和不适用持久化时的性能相差无几。用户最多只会丢失一秒内产生的数据。当硬盘忙于写入操作时,Redis会优雅的放慢自己的速度来适应硬盘的最大写入速度。
-
no
Redis将不对aof文件有任何显示的同步操作,由操作系统决定何时对aof文件进行同步。这个选择不会对Redis带来性能的影响,但是操作系统崩溃时,会丢失数据。此外,用户的硬盘写入速度较慢,缓冲区被等待写入的数据填满时,Redis的写入操作将被阻塞,导致Redis处理命令请求的速度变慢。一般不推荐使用。
-
-
重写(压缩)aof文件
重写我的理解为将同一个key的多次写入操作,处理成最终结果的一条写入命令。这样一来就就行了压缩。
Redis的不断运行,命令增多,进而追加的aof文件也越来越大(占用硬盘空间越来越大,还原操作的时间越来越长)。
除了设置的
auto-aof-rewrite-percentage 100
和auto-aof-rewrite-min-size 64mb
,客户端也可以发送BGREWRITEAOF
命令。BGREWRITEAOF
命令同样会创建子进程来对AOF进行重写。那么因创建子进程导致的性能问题,内存占用在AOF中也会出现。而且在进行AOF重写并删除旧文件的时候,旧文件过大可能会导致操作系统挂起数秒。
总结
无论是使用RDB还是AOF,将数据持久化到硬盘是非常有必要的,但是还要对数据进行备份。
在既使用RDB,有使用AOF的情况下,Redis启动优先加载aof文件。
参考文献:《Redis 实战》