欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Redis持久化

程序员文章站 2022-07-14 19:05:36
...

    Redis支持两种方式的持久化,一种是 RDB 方式,另一种是 AOF 方式。前者会根据指定的规则“定时”将内存中的数据存储在硬盘上,而后者在每次执行命令后将命令本身记录下来。两种持久化方式可以单独使用其中一种,但更多情况下是将二者结合使用。

 

1、RDB 方式

 

RDB 方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时 Redis 会自动将内存中的所有数据生成一份副本存储在硬盘上,这个过程即为“快照”。Redis会在以下几种情况下对数据进行快照:

 

A、根据配置规则进行自动快照——Redis 允许用户自定义快照条件,当符合快照条件时,Redis会自动执行快照操作。可在配置文件中自定义,由两个参数构成:时间窗口M和改动的键的个数N。每当时间M内被更改的键的个数大于N时,即符合自动快照条件。

 

save 900 1 在15分钟(900秒)内有一个或一个以上的键被更改则进行快照。

 

B、用户执行 SAVE 或 BGSAVE 命令——除了让Redis自动进行快照外,当进行服务重启、手动迁移以及备份时我们也会需要手动执行快照操作。

 

当执行 SAVE 命令时,Redis同步地进行快照操作,在快照执行的过程中会阻塞所有来自客户端的请求。当数据库中的数据比较多时,这一过程会导致Redis较长时间不响应。

 

需要手动执行快照时推荐时使用BGSAVE 命令。该命令可以在后台异步地进行快照操作,快照的同时服务器还可以继续响应来自客户端的请求。

 

执行 BGSAVE 后Redis会立即返回OK表示开始执行快照操作,如果想知道快照是否完成,可以通过 LASTSAVE 命令获取最近一次成功执行快照的时间,返回结果是一个Unix时间戳。

 

C、执行 FLUSHALL 命令——当执行该命令式,Redis会清除数据库中的所有数据。不论清空数据库的过程是否触发了自动快照条件,只要自动快照条件不为空,Redis就会执行一次快照操作。当没有定义自动快照条件时,执行该命令则不会进行快照。

 

D、执行复制(replication)时——当设置了主从模式时,Redis会在复制初始化时自动快照。当使用复制操作时,即使没有定义自动快照条件,并且没有手动执行过快照操作,也会生成 RDB 快照文件。

 

2、快照原理

 

Redis 默认会将快照文件存储在Redis当前进程的工作目录中的 dump.rdb 文件中,可以通过配置 dir 和 dbfilename 两个参数分别指定快照文件的存储路径和文件名。快照过程如下:

 

Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);父进程继续接受并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件;当子进程写入完所有的数据后会用该临时文件替换旧的 RDB 文件,至此一次快照操作完成。

 

在执行 fork 的时候操作系统会使用写时复制(copy-on-write)策略,即 fork 函数发生的一刻父子进程共享同一内存数据,当父进程要更改其中某片数据时(如执行一个写命令),操作系统会将该片数据复制一份以保证子进程的数据不受影响,

 

所以新的 RDB 文件存储的是执行fork一刻的内存数据。

 

Redis启动后会读取 RDB 快照文件,将数据从硬盘载入到内存。

 

通过 RDB 方式实现持久化,一旦 Redis 异常退出,就会丢失最后一次快照以后更改的所有数据。如果数据相对重要,希望将损失降到最小,则可以使用 AOF 方式进行持久化。

 

3、AOF 方式

 

当使用 Redis 存储非临时数据时,一般需要打开 AOF 持久化来降低进程中止导致的数据丢失。AOF 可以将 Redis 执行的每一条写命令追加到硬盘文件中,这一过程显然会降低 Redis 性能,但是大部分情况下这个影响是可以接受的,另外使用较快的硬盘可以提高 AOF 的性能。

 

默认情况下 Redis 没有开启 AOF(append only file) 方式的持久化,可以通过 appendonly 参数启用: appendonly yes

 

开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis就会将该命令写入硬盘中的 AOF 文件。

 

AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir 参数设置的,默认的文件名是 appendonly.aof ,可以通过 appendfilename 参数修改:appendfilename appendonly.aof

 

每当达到一定条件时 Redis 就会自动重写 AOF 文件,这个条件可以在配置文件中设置:

 

auto-aof-rewrite-percentage 100 当目前的 AOF 文件大小超过上一次重写时的 AOF 文件大小的百分之多少时会再次进行重写,如果之前没有重写过,则以启动时的 AOF 文件大小为依据。

 

auto-aof-rewrite-min-size 64mb 限制了允许重写的最小 AOF 文件大小,通常在 AOF 文件很小的情况下即使其中有很多冗余的命令我们也并不太关心。

 

除了让 Redis 自动执行重写外,我们还可以主动使用 BGREWRITEAOF 命令手动执行 AOF 重写。

 

重写的过程只和内存中的数据有关,和之前的 AOF 文件无关。在启动时 Redis 会逐个执行 AOF 文件中的命令来将硬盘中的数据载入到内存中,载入的速度相较 RDB 会慢一些。

 

4、同步硬盘数据

 

虽然每次执行更改数据库内容的操作时,AOF 都会讲命令记录在 AOF 文件中,但是事实上,由于操作系统的缓存机制,数据并没有真正地写入硬盘,而是进入了系统的硬盘缓存。

 

在默认情况下系统每30秒会执行一次同步操作,以便将硬盘缓存中的内容真正地写入硬盘,在这30秒的过程中如果系统异常退出则会导致硬盘缓存中的数据丢失。

 

一般来讲启用 AOF 持久化的应用都无法容忍这样的损失,这就需要 Redis 在写入 AOF 文件后主动要求系统将魂村内容同步到硬盘中。

 

在 Redis 中我们可以通过 appendfsync 参数设置同步的时机:

 

#appendfsync always ——每次执行写入都会执行同步,这是最安全也是最慢的方式。

 

appendfsync everysec ——默认规则,即每秒执行一次同步操作。既兼顾了性能又保证了安全。

 

#appendfsync no ——不主动进行同步操作,而是完全交由操作系统来做(即每30秒一次),这是最快但最不安全的方式。

 

Redis 允许同时开启 AOF 和 RDB,既保证了数据安全有使得进行备份等操作十分容易。此时重新启动 Redis 后 Redis 会使用 AOF 文件来恢复数据,因为 AOF 方式的持久化可能丢失的数据更少。