Redis 持久化数据
# 80.Redis 持久化数据
Redis 是一个内存数据库,当 Redis 重启,或者电脑重启后,数据会丢失,我们可以将 Redis 内存中的数据持久化保存到硬盘的文件中。Redis 支持的持久化机制有两种:RDB(Redis Database)和 AOF(Append Only File)
# RDB
RDB:默认方式,不需要进行配置,默认就使用这种机制。
原理:在一定的间隔时间中,检测 key 的变化情况,然后持久化数据(生成一个快照,snapshotting),保存到 rdb 结尾的文件。推荐使用该种方式,效率比较高。
# RDB 默认配置
我们打开 redis.windwos.conf
文件,在 137 行可以看到这样的配置:
# 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 behaviour 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
最后 3 行配置就是 RDB 的默认配置,通过上面的注释,我们可以知道 save 配置的含义:
- save 900 1:是指 after 900 sec (15 min) if at least 1 key changed,也就是 15 分钟后(900 秒),如果至少 1 个 key 变化了,则保存数据
- save 300 10:after 300 sec (5 min) if at least 10 keys changed,也就是 5 分钟后(300 秒),如果至少 10 个 key 变化了,则保存数据;
- save 60 10000:after 60 sec if at least 10000 keys changed,也就是 1 分钟后(60 秒),如果至少 10000 个 key 变化了,则保存数据;
# 修改默认配置
为了方便演示,我们新建一个 redis.conf 文件,文件内容如下:
save 10 5
这表示 10 秒内,如果有 5 个 key 发生变化(或者一个 key 变化了 5 次),就会保存数据。
然后我们打开命令行,并指定配置文件:
D:\Projects\Redis-x64-3.0.504>redis-server redis.conf
然后打开 redis-cli,首先查看下有没有 key,然后在 10 秒内操作一个 key5 次:
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>
127.0.0.1:6379> set username 1
OK
127.0.0.1:6379> set username 2
OK
127.0.0.1:6379> set username 3
OK
127.0.0.1:6379> set username 4
OK
127.0.0.1:6379> set username 5
OK
2
3
4
5
6
7
8
9
10
11
12
13
我们可以看到,redis 的日志告诉我们,10 秒内有 5 个变化,保存数据中
并且在 Redis 的目录中,也存在一个 rdb 结尾的文件:
# 重启 Redis 并测试
我们重启 redis 服务端,然后重新打开客户端,也可获取到之前设置的值:
127.0.0.1:6379> keys *
1) "username"
127.0.0.1:6379> get username
"5
2
3
4
5
6
至于时间间隔和变化的 key 数量到底怎么配置,得取决于项目需要。
# 手动备份
除了让 Redis 自动进行快照外,当进行服务重启、手动迁移以及备份时我们也会需要手动执行快照操作。Redis 提供了两个命令来完成这一任务。
1.SAVE 命令
当执行 SAVE 命令时,Redis 同步地进行快照操作,在快照执行的过程中会阻塞所有来自客户端的请求。当数据库中的数据比较多时,这一过程会导致 Redis 较长时间不响应,所以要尽量避免在生产环境中使用这一命令
2.BGSAVE 命令
需要手动执行快照时推荐使用 BGSAVE 命令。BGSAVE 命令可以在后台异步地进行快照操作,快照的同时服务器还可以继续响应来自客户端的请求。
执行 BGSAVE 后 Redis 会立即返回 OK 表示开始执行快照操作,如果想知道快照是否完成,可以通过 LASTSAVE 命令获取最近一次成功执行快照的时间,返回结果是一个 Unix 时间戳,如:
redis> LASTSAVE
(integer) 1423537869
2
执行自动快照时 Redis 采用的策略即是异步快照。
# AOF
AOF:通过日志记录的方式,记录每一条命令的操作。可以配置成每一次命令操作后,就持久化数据,这样的话就跟数据库很像,执行一条 SQL 就保存到数据库里,但这样配置的话性能较差。
# AOF 默认配置
打开 redis.windwos.conf
文件,可以看到这样的配置(大约在配置文件 501 行左右)
############################## 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"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
第 21 行里,可以看到配置了 appendonly no
,表明关闭 AOF 模式的记录;可以通过修改为 yes 来开启 AOF
appendonly yes
第 24 行的配置
appendfilename "appendonly.aof"
表明将数据保存到 appendonly.aof
文件里,由于我们没有指定路径,则默认在 Redis 的路径下。
虽然每次执行更改数据库内容的操作时,AOF 都会将命令记录在 AOF 文件中,但是事实上,由于操作系统的缓存机制,数据并没有真正地写入硬盘,而是进入了系统的硬盘缓存。在默认情况下系统每 30 秒会执行一次同步操作,以便将硬盘缓存中的内容真正地写入硬盘,在这 30 秒的过程中如果系统异常退出则会导致硬盘缓存中的数据丢失。一般来讲启用 AOF 持久化的应用都无法容忍这样的损失,这就需要 Redis 在写入 AOF 文件后主动要求系统将缓存内容同步到硬盘中。
在 redis.windwos.conf
文件第 550 行左右,关于 AOF 还有这样的配置:
# appendfsync always
appendfsync everysec
# appendfsync no
2
3
配置的含义如下:
appendfsync always
:每一次操作都进行持久化。每个 Redis 写命令都要同步写入硬盘。这样做会严重降低 Redis 的速度appendfsync everysec
:每隔一秒进行一次持久化,显式地将多个写命令同步到硬盘,默认值,一般够用appendfsync no
: 不进行持久化,让操作系统来决定应该何时进行同步(即每 30s 一次)
我们在 redis.conf 配置文件里,加上如上的配置,现在文件内容如下:
save 10 5
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
2
3
4
5
# 重启 Redis 并测试
我们重启 Redis 服务端和客户端,并添加一个 key:
127.0.0.1:6379> set password 123456
OK
2
然后我们就可以看到会生成一个 aof 文件:
文件里有如下内容:
这些内容,除了 password 和 123456 之外,其他的都看不懂是什么,没关系,我们只需知道 AOF 是通过文本形式保存数据即可(RDB 则是二进制文件)。
我们重启 redis 服务端,然后重新打开客户端,也可以获取到之前设置的 password 的值,这里就不演示了
# 压缩 AOF
举个例子,当我们执行了如下命令:
SET foo 1
SET foo 2
SET foo 3
2
3
前 2 条命令其实都是冗余的,因为这两条的执行结果会被第三条命令覆盖。随着执行的命令越来越多,AOF 文件的大小也会越来越大,即使内存中实际的数据可能并没有多少。
很自然地,我们希望 Redis 可以自动优化 AOF 文件,就上例而言,就是将前两条无用的记录删除,只保留第三条。实际上 Redis 也正是这样做的,每当达到一定条件时 Redis 就会自动重写 AOF 文件,这个条件可以在配置文件中设置:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
2
auto-aof-rewrite-percentage 参数的意义是:当目前的 AOF 文件大小超过上一次重写时的 AOF 文件大小的百分之多少时会再次进行重写,如果之前没有重写过,则以启动时的 AOF 文件大小为依据。
auto-aof-rewrite-min-size 参数限制了允许重写的最小 AOF 文件大小,通常在 AOF 文件很小的情况下即使其中有很多冗余的命令我们也并不太关心。
除了让 Redis 自动执行重写外,我们还可以主动使用 BGREWRITEAOF 命令手动执行 AOF 重写。
重写的过程只和内存中的数据有关,和之前的 AOF 文件无关,这与 RDB 很相似,只不过二者的文件格式完全不同。
# 总结
以上持久化配置,在遇到特殊情况的时候(宕机、或有异常),并不能保证所有数据都不丢失,但能保证大部分数据都不丢失。如果想要绝对的数据安全,还得使用关系型数据库。
这两种持久化方法既可以同时使用,又可以单独使用,在某些情况下甚至可以两种方法都不使用,具体选择哪种持久化方法需要根据用户的数据以及应用来决定。