Redis持久化机制

https://redis.io/topics/persistence

Redis速度快,很大一部分原因是因为它所有的数据都存储在内存中。如果断电或者宕机,都会导致内存中的数据丢失。为了实现重启后数据不丢失,Redis提供了两种持久化的方案,—种是 RDB 快照(Redis DataBase),—种是 AOF (Append Only File)。持久化是Redis跟Memcache的主要区别之一。

RDB

RDB是Redis默认的持久化方案(注意如果开启了 AOF,优先用AOF)。当满足一定条件的时候,会把当前内存中的数据写入磁盘,生成一个快照文件dump.rdb。Redis 重启会通过加载dump.rdb文件恢复数据。

什么时候写入rdb文件?

RDB 触发

1.自动配置触发

a)配置规则触发

redis.conf, SNAPSHOTTING,其中定义了触发把数据保存到磁盘的触发频率。如果不需要rdb方案,注释save或者配置成空字符串""。

save 900 1 # 900秒内至少有一个key被修改(包括添加) 
save 300 10 # 400秒内至少有10个key被修改
save 60 10000 # 60秒内至少有10000个key被修改

注意上面的配置是不冲突的,只要满足任意一个都会触发。
用lastsave命令可以查看最近一次成功生成快照的时间。
rdb文件位置和目录(默认在安装根目录下):

#文件路径
dir ./
#文件名称
dbfilename dump.rdb
#是否以LZF压缩rdb文件 
rdbcompression yes
#开启数据校验
rdbchecksum yes
参数 说明
dir rdb文件默认在启动目录下(相对路径)
config get dir 获取
dbfilename 文件名称
rdbcompression 开启压缩可以节省存储空间,但是会消耗一些CPU的计算时间,默认开启
rdbchecksum 使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。

除了根据配置触发生成RDB, RDB还有两种自动触发方式:
b) shutdown触发,保证服务器正常关闭。
c) flushall, rdb文件是空的,没什么意义(删掉dump.rdb)。

2.手动触发

如果我们需要重启服务或者迁移数据,这个时候就需要手动触RDB快照保存。Redis 提供了两条命令:

a) save
save在生成快照的时候会阻塞当前Redis服务器,Redis不能处理其他命令。如果内存中的数据比较多,会造成Redis长时间的阻塞。生产环境不建议使用这个命令。
为了解决这个问题,Redis提供了第二种方式。

b) bgsave
执行bgsave时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。
具体操作是Redis进程执行fork操作创建子进程(copy-on-write) , RDB持久化过程由子进程负责,完成后自动结束。它不会记录fork之后产生的数据。阻塞只发生在fork阶段,一般时间很短。

RDB数据的恢复

1.shutdown 持久化
添加键值

redis> set kl 1
redis> set k2 2
redis> set k3 3
redis> set k4 4
redis> set k5 5

停服务器,触发save

redis> shutdown

备份dump.rdb文件

cp dump.rdb dump.rdb.bak

启动服务器

./redis-server /usr/local/soft/redis-6.0.9/redis.conf

查询数据:

redis> keys

2.模拟数据丟失

redis> flushall

停服务器

./redis-server /usr/local/soft/redis-6.0.9/redis.conf

没有数据:

redis> keys *

3.通过备份文件恢复数据

停服务器

redis> shutdown

重命名备份文件

mv dump.rdb.bak dump.rdb

启动服务器

./redis-server /usr/local/soft/redis-6.0.9/redis.conf

查看数据

redis> keys *

RDB文件的优势和劣势

—、优势
1.RDB是一个非常紧凑(compact)的文件,它保存了 redis在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复。
2.生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
3.RDB在恢复大数据集时的速度比AOF的恢复速度要快。
二、劣势
1、RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,频繁执行成本过高。
2、在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照之后的所有修改(数据有丟失)。如果数据相对来说比较重要,希望将损失降到最小,则可以使用AOF方式进行持久化。

AOF

Append Only File
AOF: Redis默认不开启。AOF采用日志的形式来记录每个写操作,并追加到文件中。开启后,执行更改Redis数据的命令时,就会把命令写入到AOF文件中。
Redis重启时会根据日志文件的内容把写指令从前到后执行一次以完成数据的恢复工作。

AOF 配置

配置文件redis.conf

#开关 
appendonly no
#文件名
appendfilename "appendonly.aof"
参数 说明
appendonly Redis默认只开启RDB持久化,开启AOF需要修改为yes
appendfilename "appendonly.aof" 路径也是通过dir参数配置config get dir

AOF文件的内容(vim査看):

*2
$6
SELECT
$1
0
*3
$3
set
$8
snail
$4
2673

问题:数据都是实时持久化到磁盘吗?

由于操作系统的缓存机制,AOF数据并没有真正地写入硬盘,而是进入了系统的硬盘缓存。什么时候把缓冲区的内容写入到AOF文件?

参数 说明
appendfsync everysec AOF持久化策略(硬盘缓存到磁盘)默认everysec
• no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快,但是不太安全;
• always表示每次写入都执行fsync,以保证数据同步到磁盘,效率很低;
• everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。通常选择everysec , 兼顾安全性和效率。

问题:文件越来越大,怎么办?

由于AOF持久化是Redis不断将写命令记录到AOF文件中,随着Redis不断的进 行,AOF的文件会越来越大,文件越大,占用服务器内存越大以及AOF恢复要求时间越长。
例如计数器增加100万次,100万个命令都记录进去了,但是结果只有1个。
为了解决这个问题,Redis新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。

可以使用命令bgrewriteaof来重写。
AOF文件重写并不是对原文件进行重新整理,而是直接读取服务器现有的键值对, 然后用一条命令去代替之前记录这个键值对的多条命令,生成一个新的文件后去替换原来的AOF文件。

#重写触发机制
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
参数 说明
auto-aof-rewrite-percentage 默认值为100。aof自动重写配置,当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当aof文件增长到一定大小的时候,Redis能够调用bgrewriteaof 对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重与过程。
auto-aof-rewrite-min-size 默认64M。设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写。

问题:重写过程中,AOF文件被更改了怎么办?

换言之,当子进程在执行AOF重写时,主进程需要执行以下三个工作:
1.处理命令请求。
2.将写命令追加到现有的AOF文件中。
3.将写命令追加到AOF重写缓存中。

另外有两个与AOF相关的参数:

参数 说明
no-appendfsync-on-rewrite 在aof重写或者写入rdb文件的时候,会执行大量IO,此时对于everysec和always的aof 模式来说,执行fsync会造成阻塞过长时间,no-appendfsync-on-rewrite字段设置为默认设置为no。如果对延迟要求很高的应用,这个字段可以设置为yes,否则还是设置为no,这样对持久化特性来说这是更安全的选择。设置为yes表示rewrite期间对新写操作不fsync, 暂时存在内存中,等rewrite完成后再写入,默认为no,建议修改为yes。Linux的默认fsync 策略是30秒。可能丢失30秒数据
aof-load-truncated aof文件可能在尾部是不完整的,当redis启动的时候,aof文件的数据被载入内存。重启可能发生在redis所在的主机操作系统宕机后,尤其在ext4文件系统没有加上data=ordered 选项,出现这种现象。redis宕机或者异常终止不会造成尾部不完整现象,可以选择让redis 退出,或者导入尽可能多的数据。如果选择的是yes,当截断的aof文件被导入的时候, 会自动发布一个log给客户端然后load。如果是no,用户必须手动redis-check-aof修复AOF 文件才可以。默认值为yes。

AOF数据恢复

重启Redis之后就会进行AOF文件的恢复。

AOF优势与劣势

优点:
1、AOF持久化的方法提供了多种的同步频率,即使使用默认的同步频率每秒同步一次,Redis最多也就丢失1秒的数据而已。
缺点:
1、对于具有相同数据的的Redis, AOF文件通常会比RDF文件体积更大(RDB存的是数据快照)。
2、虽然AOF提供了多种同步的频率,默认情况下,每秒同步一次的频率也具有较高的性能。在高并发的情况下,RDB比AOF具好更好的性能保证。

两种方案比较

那么对于AOF和RDB两种持久化方式,我们应该如何选择呢?
如果可以忍受一小段时间内数据的丢失,毫无疑问使用RDB是最好的,定时生成 RDB快照(snapshot)非常便于进行数据库备份,并且RDB恢复数据集的速度也要比 AOF恢复的速度要快。
否则就使用AOF重写。但是一般情况下建议不要单独使用某一种持久化机制,而是应该两种一起用,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。

posted @ 2021-02-25 23:50  snail灬  阅读(28)  评论(0编辑  收藏  举报