13.Redis的持久化

 

Redis的持久化

1. 概述

Redis提供了不同范围的持久性选项:

  • RDB持久性按指定的时间间隔执行数据集的时间点快照。

  • AOF持久性会记录服务器接收的每个写入操作,这些操作将在服务器启动时再次播放,以重建原始数据集。使用与Redis协议本身相同的格式记录命令,并且仅采用追加方式。当日志太大时,Redis可以在后台重写日志。

  • 如果希望只要服务器在运行时数据就一直存在,则可以完全禁用持久性。

  • 可以在同一实例中同时使用AOF和RDB。请注意,在这种情况下,当Redis重新启动时,AOF文件将用于重建原始数据集,因为它可以保证是最完整的。

2. RDB【Redis DataBase】

2.1. 什么是RDB

(1) RDB的优势

  • RDB是Redis数据的非常紧凑的单文件时间点表示。RDB文件非常适合备份。例如,您可能希望在最近的24小时内每小时存档一次RDB文件,并在30天之内每天保存一次RDB快照。这使您可以在发生灾难时轻松还原数据集的不同版本。

  • RDB对于灾难恢复非常有用,它是一个紧凑的文件,可以传输到远程数据中心或Amazon S3(可能已加密)上。

  • RDB最大限度地提高了Redis的性能,因为Redis父进程为了持久化所需要做的唯一工作就是分派一个孩子,其余的都将做。父实例将永远不会执行磁盘I/O等操作。

  • 与AOF相比,RDB允许大型数据集更快地重启。

(2) RDB的缺点

  • 如果您需要最大程度地减少数据丢失的可能性(如果Redis停止工作,例如在断电之后),则RDB不好。您可以在生成RDB的位置配置不同的保存点(例如,在至少五分钟之后,对数据集进行100次写入,但是可以有多个保存点)。但是,通常会每隔五分钟或更长时间创建一次RDB快照,因此,如果Redis出于任何原因在没有正确关闭的情况下停止工作,则应该准备丢失最近几分钟的数据。

  • RDB需要经常使用fork()才能使用子进程将其持久化在磁盘上。如果数据集很大,Fork()可能很耗时,并且如果数据集很大且CPU性能不佳,则可能导致Redis停止为客户端服务几毫秒甚至一秒钟。AOF也需要fork(),但您可以调整要重写日志的频率,而无需在持久性上进行权衡。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
################################ SNAPSHOTTING  ################################
#
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# In the example below the behavior will be to save:
# after 900 sec (15 min) if at least 1 key changed
# after 300 sec (5 min) if at least 10 keys changed
# after 60 sec if at least 10000 keys changed
#
# Note: you can disable saving completely by commenting out all "save" lines.
#
# It is also possible to remove all the previously configured save
# points by adding a save directive with a single empty string argument
# like in the following example:
#
# save ""

save 900 1
save 300 10
save 60 10000

在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

2.2 什么是FORK

Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

2.3 保存位置及配置位置

Rdb保存的是dump.rdb文件

2.4 如何触发RDB快照

1
2
3
save 900 1
save 300 10
save 60 10000

执行flushall命令,也会产生dump.rdb文件,但里面是空的,无意义

2.5 如何恢复数据

将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可

CONFIG GET dir: 获取目录

2.6,优点

  • 适合大规模的数据恢复

  • 对数据完整性和一致性要求不高

2.7,缺点

  • 在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改

  • Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑

2.8 Demo

1
2
3
4
5
6
7
logfile "my_redis_log.log"

save 30 10

dbfilename my_redis_dump.rdb

dir /usr/local/redis-6.0.9/my_redis_conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost bin]# ./redis-server /usr/local/redis-6.0.9/my_redis_conf/my_redis_6379.conf
[root@localhost bin]# ls -l
total 36272
-rw-r--r--. 1 root root 0 Dec 5 22:08 my_redis_log.log
-rwxr-xr-x. 1 root root 4796896 Nov 29 11:49 redis-benchmark
-rwxr-xr-x. 1 root root 9094264 Nov 29 11:49 redis-check-aof
-rwxr-xr-x. 1 root root 9094264 Nov 29 11:49 redis-check-rdb
-rwxr-xr-x. 1 root root 5049408 Nov 29 11:49 redis-cli
lrwxrwxrwx. 1 root root 12 Nov 29 11:49 redis-sentinel -> redis-server
-rwxr-xr-x. 1 root root 9094264 Nov 29 11:49 redis-server
[root@localhost my_redis_conf]# ls -l
total 172
-rw-r--r--. 1 root root 84999 Dec 5 22:07 my_redis_6379.conf
-rw-r--r--. 1 root root 2517 Dec 5 22:08 my_redis_log.log

bindir两个文件目录下都生成了my_redis_log.log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost bin]# ./redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/usr/local/redis-6.0.9/my_redis_conf"
127.0.0.1:6379> quit
[root@localhost my_redis_conf]# ll
total 176
-rw-r--r--. 1 root root 84999 Dec 5 22:07 my_redis_6379.conf
-rw-r--r--. 1 root root 92 Dec 5 22:14 my_redis_dump.rdb
-rw-r--r--. 1 root root 2568 Dec 5 22:14 my_redis_log.log

dir目录下生成了my_redis_dump.rdb文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 k6 v6 k7 v7 k8 v8 k9 v9 k10 v10
OK
127.0.0.1:6379> keys *
1) "k5"
2) "k9"
3) "k6"
4) "k8"
5) "k3"
6) "k7"
7) "k1"
8) "k2"
9) "k10"
10) "k4"
[root@localhost my_redis_conf]# ll
total 176
-rw-r--r--. 1 root root 84999 Dec 5 22:07 my_redis_6379.conf
-rw-r--r--. 1 root root 169 Dec 5 22:20 my_redis_dump.rdb
-rw-r--r--. 1 root root 2913 Dec 5 22:20 my_redis_log.log

可以看到my_redis_dump.rdb文件的大小有变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
127.0.0.1:6379> SHUTDOWN
not connected> quit

[root@localhost my_redis_conf]# ll
total 180
-rw-r--r--. 1 root root 84999 Dec 5 22:07 my_redis_6379.conf
-rw-r--r--. 1 root root 169 Dec 5 22:27 my_redis_dump.rdb
-rw-r--r--. 1 root root 6021 Dec 6 10:33 my_redis_log.log
[root@localhost my_redis_conf]# mv my_redis_dump.rdb my_redis_dump.rdb.bak
[root@localhost my_redis_conf]# ll
total 180
-rw-r--r--. 1 root root 84999 Dec 5 22:07 my_redis_6379.conf
-rw-r--r--. 1 root root 169 Dec 5 22:27 my_redis_dump.rdb.bak
-rw-r--r--. 1 root root 6021 Dec 6 10:33 my_redis_log.log
-rw-r--r--. 1 root root 84926 Dec 4 22:46 redis.conf

[root@localhost bin]# ./redis-server /usr/local/redis-6.0.9/my_redis_conf/my_redis_6379.conf
[root@localhost bin]# ./redis-cli
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> SHUTDOWN
not connected> quit

可以看到: (1)关闭数据库,(2)移除my_redis_dump.rdb文件,(3)再启动redis之后,原来的数据就丢失了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[root@localhost my_redis_conf]# ll
total 188
-rw-r--r--. 1 root root 84999 Dec 5 22:07 my_redis_6379.conf
-rw-r--r--. 1 root root 92 Dec 6 10:36 my_redis_dump.rdb
-rw-r--r--. 1 root root 169 Dec 5 22:27 my_redis_dump.rdb.bak
-rw-r--r--. 1 root root 9182 Dec 6 10:36 my_redis_log.log
-rw-r--r--. 1 root root 84926 Dec 4 22:46 redis.conf
[root@localhost my_redis_conf]# rm -f my_redis_dump.rdb
[root@localhost my_redis_conf]# ll
total 184
-rw-r--r--. 1 root root 84999 Dec 5 22:07 my_redis_6379.conf
-rw-r--r--. 1 root root 169 Dec 5 22:27 my_redis_dump.rdb.bak
-rw-r--r--. 1 root root 9182 Dec 6 10:36 my_redis_log.log
-rw-r--r--. 1 root root 84926 Dec 4 22:46 redis.conf

[root@localhost my_redis_conf]# mv my_redis_dump.rdb.bak my_redis_dump.rdb
[root@localhost my_redis_conf]# ll
total 184
-rw-r--r--. 1 root root 84999 Dec 5 22:07 my_redis_6379.conf
-rw-r--r--. 1 root root 169 Dec 5 22:27 my_redis_dump.rdb
-rw-r--r--. 1 root root 9182 Dec 6 10:36 my_redis_log.log
-rw-r--r--. 1 root root 84926 Dec 4 22:46 redis.conf

[root@localhost bin]# ./redis-server /usr/local/redis-6.0.9/my_redis_conf/my_redis_6379.conf
[root@localhost bin]# ./redis-cli
127.0.0.1:6379> keys *
1) "k6"
2) "k9"
3) "k10"
4) "k4"
5) "k5"
6) "k1"
7) "k7"
8) "k2"
9) "k8"
10) "k3"

可以看到(1)关闭数据库,关闭数据库后,如果没有my_redis_dump.rdb文件,则会新生成一个my_redis_dump.rdb文件,(2)删除新生成的my_redis_dump.rdb文件,(3)还原之前的my_redis_dump.rdb文件,(4)再启动redis之后,原来的数据就恢复了。

2.9 数据备份

因此数据库数据备份即定期备份dump.rdb文件,在需要恢复数据时,将dump.rdb文件复制到相应目录,再重启redis即可。

3,AOF

3.1 概述

(1) AOF的优势

  • 使用AOF Redis更加持久:您可以使用不同的fsync策略:完全没有fsync,每秒fsync,每个查询fsync。使用默认策略fsync时,每秒的写入性能仍然很高(fsync是使用后台线程执行的,并且当没有fsync进行时,主线程将尝试执行写入操作。),但是您只能损失一秒钟的写入时间。

  • AOF日志是仅追加的日志,因此,如果断电,则不会出现寻道或损坏问题。即使由于某种原因(磁盘已满或其他原因)以半写命令结束日志,redis-check-aof工具也可以轻松修复它。

修复数据文件的工具:

1
2
-rwxr-xr-x. 1 root root 9094264 Nov 29 11:49 redis-check-aof
-rwxr-xr-x. 1 root root 9094264 Nov 29 11:49 redis-check-rdb
  • Redis太大时,Redis能够在后台自动重写AOF。重写是完全安全的,因为Redis继续追加到旧文件时,会生成一个全新的文件,其中包含创建当前数据集所需的最少操作集,一旦准备好第二个文件,Redis会切换这两个文件并开始追加到新的那一个。

  • AOF以易于理解和解析的格式包含所有操作的日志。您甚至可以轻松导出AOF文件。例如,即使您使用FLUSHALL命令刷新了所有错误文件,如果在此期间未执行任何日志重写操作,您仍然可以保存数据集,只是停止服务器,删除最新命令,然后重新启动Redis。

(2) AOF的缺点

  • 对于相同的数据集,AOF文件通常大于等效的RDB文件。

  • 根据确切的fsync策略,AOF可能比RDB慢。通常,在将fsync设置为每秒的情况下,性能仍然很高,并且在禁用fsync的情况下,即使在高负载下,它也应与RDB一样快。即使在巨大的写负载情况下,RDB仍然能够提供有关最大延迟的更多保证。

  • 过去,我们在特定命令中遇到过罕见的错误(例如,其中一个涉及阻止命令,例如BRPOPLPUSH),导致生成的AOF在重载时无法重现完全相同的数据集。这些错误很少见,我们在测试套件中进行了测试,自动创建了随机的复杂数据集,然后重新加载它们以检查一切是否正常。但是,RDB持久性几乎是不可能的。更明确地说:Redis AOF通过增量更新现有状态来工作,就像MySQL或MongoDB一样,而RDB快照一次又一次地创建所有内容,从概念上讲更健壮。但是-1)请注意,每次Redis重写AOF时,都会从数据集中包含的实际数据开始从头开始重新创建AOF,与始终附加AOF文件(或重写为读取旧AOF而不是读取内存中的数据)相比,提高了对错误的抵抗力。2)我们从未收到过有关真实环境中检测到的AOF损坏的用户报告。

3.2 原理

以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

3.3 保存位置及位置配置

Aof保存的是appendonly.aof文件

3.4 AOF启动/修复/恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
############################## APPEND ONLY MODE ###############################

# By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check http://redis.io/topics/persistence for more information.

appendonly no

# The name of the append only file (default: "appendonly.aof")

appendfilename "appendonly.aof"

(1) 正常恢复

  1. 启动:设置Yes  修改默认的appendonly no,改为yes

  2. 将有数据的aof文件复制一份保存到对应目录(config get dir)

  3. 恢复:重启redis然后重新加载

(2) 异常恢复

  1. 启动:设置Yes   修改默认的appendonly no,改为yes

  2. 备份被写坏的AOF文件

  3. 修复:  Redis-check-aof –fix进行修复

  4. 恢复:重启redis然后重新加载

3.5 优势

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use "everysec".

# appendfsync always
appendfsync everysec
# appendfsync no

  • appendfsync always: 每修改同步,同步持久化,每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好。

  • appendfsync everysec: 每秒同步,异步操作,每秒记录,如果一秒内宕机,有数据丢失。

  • appendfsync no: 不同步,从不同步。

3.5,劣势

相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb

3.6 Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@localhost bin]# ./redis-server /usr/local/redis-6.0.9/my_redis_conf/my_redis_6379.conf
[root@localhost bin]# ./redis-cli
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> keys *
(empty array)

[root@localhost my_redis_conf]# ll
total 192
-rw-r--r--. 1 root root 0 Dec 6 11:12 my_appendonly_6379.aof
-rw-r--r--. 1 root root 85008 Dec 6 11:12 my_redis_6379.conf
-rw-r--r--. 1 root root 169 Dec 6 10:37 my_redis_dump.rdb
-rw-r--r--. 1 root root 18035 Dec 6 11:23 my_redis_log.log
-rw-r--r--. 1 root root 84926 Dec 4 22:46 redis.conf

可以看到,如果同时开启rdb和aof模式,则读取aof进行数据恢复,没有读取rdb,因此keys *是空的。

一启动redis就生成aof文件了。

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> FLUSHALL
OK

[root@localhost my_redis_conf]# ll
total 200
-rw-r--r--. 1 root root 41 Dec 6 11:26 my_appendonly_6379.aof
-rw-r--r--. 1 root root 85008 Dec 6 11:12 my_redis_6379.conf
-rw-r--r--. 1 root root 92 Dec 6 11:26 my_redis_dump.rdb
-rw-r--r--. 1 root root 20603 Dec 6 11:26 my_redis_log.log
-rw-r--r--. 1 root root 84926 Dec 4 22:46 redis.conf

执行完FLUSHALL命令之后,aof和rdb文件的大小都有变化

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 k6 v6
OK

[root@localhost my_redis_conf]# ll
total 200
-rw-r--r--. 1 root root 152 Dec 6 11:32 my_appendonly_6379.aof
-rw-r--r--. 1 root root 85008 Dec 6 11:12 my_redis_6379.conf
-rw-r--r--. 1 root root 92 Dec 6 11:26 my_redis_dump.rdb
-rw-r--r--. 1 root root 20603 Dec 6 11:26 my_redis_log.log
-rw-r--r--. 1 root root 84926 Dec 4 22:46 redis.conf

有6个key更新,所以只有aof更新,rdb没有更新

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 k6 v6 k7 v7 k8 v8 k9 v9 k10 v10
OK

[root@localhost my_redis_conf]# ll
total 200
-rw-r--r--. 1 root root 329 Dec 6 11:34 my_appendonly_6379.aof
-rw-r--r--. 1 root root 85008 Dec 6 11:12 my_redis_6379.conf
-rw-r--r--. 1 root root 169 Dec 6 11:34 my_redis_dump.rdb
-rw-r--r--. 1 root root 20948 Dec 6 11:34 my_redis_log.log
-rw-r--r--. 1 root root 84926 Dec 4 22:46 redis.conf

有10个key更新,所以aof和rdb都更新了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
127.0.0.1:6379> SHUTDOWN
not connected> quit
[root@localhost bin]#

[root@localhost my_redis_conf]# mv my_appendonly_6379.aof my_appendonly_6379.aof.bak
[root@localhost my_redis_conf]# ll
total 200
-rw-r--r--. 1 root root 329 Dec 6 11:34 my_appendonly_6379.aof.bak
-rw-r--r--. 1 root root 85008 Dec 6 11:12 my_redis_6379.conf
-rw-r--r--. 1 root root 169 Dec 6 11:39 my_redis_dump.rdb
-rw-r--r--. 1 root root 21337 Dec 6 11:39 my_redis_log.log

[root@localhost bin]# ./redis-server /usr/local/redis-6.0.9/my_redis_conf/my_redis_6379.conf
[root@localhost bin]# ./redis-cli
127.0.0.1:6379>
127.0.0.1:6379> keys *
(empty array)

[root@localhost my_redis_conf]# ll
total 200
-rw-r--r--. 1 root root 0 Dec 6 11:39 my_appendonly_6379.aof
-rw-r--r--. 1 root root 329 Dec 6 11:34 my_appendonly_6379.aof.bak
-rw-r--r--. 1 root root 85008 Dec 6 11:12 my_redis_6379.conf
-rw-r--r--. 1 root root 169 Dec 6 11:39 my_redis_dump.rdb
-rw-r--r--. 1 root root 23854 Dec 6 11:39 my_redis_log.log

如果同时开启rdb和aof模式,则读取aof进行数据恢复,即使rdb文件中有数据也不读取rdb,因此keys *是空的。

如果没有找到aof文件,则新生成一个aof文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
127.0.0.1:6379> SHUTDOWN
not connected> quit

[root@localhost my_redis_conf]# ll
total 200
-rw-r--r--. 1 root root 0 Dec 6 11:39 my_appendonly_6379.aof
-rw-r--r--. 1 root root 329 Dec 6 11:34 my_appendonly_6379.aof.bak
-rw-r--r--. 1 root root 85008 Dec 6 11:12 my_redis_6379.conf
-rw-r--r--. 1 root root 92 Dec 6 11:44 my_redis_dump.rdb
-rw-r--r--. 1 root root 24243 Dec 6 11:44 my_redis_log.log
-rw-r--r--. 1 root root 84926 Dec 4 22:46 redis.conf
[root@localhost my_redis_conf]# rm -f my_appendonly_6379.aof

[root@localhost my_redis_conf]# ll
total 200
-rw-r--r--. 1 root root 329 Dec 6 11:34 my_appendonly_6379.aof.bak
-rw-r--r--. 1 root root 85008 Dec 6 11:12 my_redis_6379.conf
-rw-r--r--. 1 root root 92 Dec 6 11:44 my_redis_dump.rdb
-rw-r--r--. 1 root root 24243 Dec 6 11:44 my_redis_log.log
[root@localhost my_redis_conf]# mv my_appendonly_6379.aof.bak my_appendonly_6379.aof
[root@localhost my_redis_conf]# ll
total 200
-rw-r--r--. 1 root root 329 Dec 6 11:34 my_appendonly_6379.aof
-rw-r--r--. 1 root root 85008 Dec 6 11:12 my_redis_6379.conf
-rw-r--r--. 1 root root 92 Dec 6 11:44 my_redis_dump.rdb
-rw-r--r--. 1 root root 24243 Dec 6 11:44 my_redis_log.log

[root@localhost bin]# ./redis-server /usr/local/redis-6.0.9/my_redis_conf/my_redis_6379.conf
[root@localhost bin]# ./redis-cli
127.0.0.1:6379> keys *
1) "k8"
2) "k5"
3) "k7"
4) "k4"
5) "k2"
6) "k10"
7) "k9"
8) "k3"
9) "k1"
10) "k6"

(1)关闭数据库,(2)移除新生成的aof文件,(3)恢复原来的aof文件,(4)启动redis,发现数据已经恢复。

4. 应该选择哪一个

4.1 官方建议

通常的指示是,如果您希望获得与PostgreSQL可以提供的功能相当的数据安全性,则应同时使用两种持久性方法。

如果您非常关心数据,但是在灾难情况下仍然可以承受几分钟的数据丢失,则可以只使用RDB。

有许多用户单独使用AOF,但我们不建议这样做,因为不时拥有RDB快照对于进行数据库备份,加快重启速度以及AOF引擎中存在错误是一个好主意。

注意:由于所有这些原因,我们将来可能会最终将AOF和RDB统一为一个持久性模型(长期计划)。

以下各节将说明有关这两个持久性模型的更多详细信息。

4.2 整理理解及处理方式

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文件,载入较新的那个。新浪微博就选用了这种架构。

5. 缓存穿透和缓存雪崩

  1. 缓存穿透

大量的查询的数据没有在缓存中。

解决方式:在启动项目时把数据加载到缓存中

  1. 缓存雪崩

大量缓存的数据同时过期,

解决方式:数据的有效期设置为随机值