Redis 持久化机制
总览
redis
数据库,可以直接用来当数据库使用,也可以当系统的缓存使用。但是 redis
大部分数据是存储在内存中的,当服务掉线重启,会造成数据的丢失。当然,redis
是有持久化线程的,我们可以利用这个持久化服务来做数据的持久化,这样当 redis
重启的时候,即可从硬盘重新读取数据,然后进行数据的恢复。 redis
的持久化方式有两种:
执行过程
redis
的 RDB
持久化是通过快照完成的。当符合一定条件的时候,redis
可以将目前的数据生成一份副本存储在硬盘。 redis
执行快照的一句有下面几种:
- 根据配置的规则
- 用户执行
SAVE
或BGSAVE
命令 - 执行
FLUSHALL
命令 - 执行复制时
配置规则
redis
可以根据用户在配置文件中配置的规则进行定时,定量的持久化。在 redis
的 conf
文件夹中配置如下:
1 | save 900 1 # 表示900秒以内有一个或以上的简直更改时进行快照 |
执行 SAVE 或 BGSAVE 命令
执行 SAVE
时,redis
会阻塞所有客户端的请求,然后进行备份。这一过程可能造成 redis
长时间无响应,所以应该尽量避免。 执行 BGSAVE
时,redis
则异步的进行快照,客户端的请求依然可以进行处理。 执行 BGSAVE
时,redis
做了以下的操作:
- 当执行
BGSAVE
的时候,redis
会使用Fork
函数复制一份当前进程(父)的副本(子) - 父进程继续接收客户端的请求,而子进程会将
Fork
的副本写入硬盘的临时文件 - 当子进程将所有数据写入临时文件时,开始替换旧的
RDB
文件
在进行 Fork 操作的时候,父子进程共享一份内存数据,当父进程需要修改某一片的数据的时候,操作系统会将这一份数据进行复制,保证子进程的读取。所以,Fork 函数执行的时候,RDB文件存储的是这一时刻的数据。 执行这一操作需要确保开启 Linux 系统允许应用程序申请超过可用内存的空间(物理空间和交换空间)。方法是在 .etc/sysctl.conf 加入 vm.overcommit_memory = 1 然后重启系统或执行 sysctl vm.overcommit_memory = 1使配置生效即可。
执行 FLUSHALL 命令
执行该命令时,数据库中的所有数据将会被清空,不论配置文件怎么配置,只要执行该命令,redis
就会执行一次快照操作。
执行复制时
只要配置主从复制时,无论有没有配置规则,都会生成 RDB
文件的快照。用于多个实例之间进行数据的同步。
AOF 方式
当使用 redis
存储非临时数据时,一般需要开启 AOF
模式来减少每次 redis
的宕机造成的数据损失。AOF
会将 redis
执行的每一条命令都写入硬盘。当然这一过程肯定对性能造成一定影响,不过可以接受。
开启AOF
默认 redis
是没有开启 AOF
模式的。可以通过配置文件来实现:
1 | appendonly yes |
开启 AOF
持久化后将会保存每一条命令,可以通过下面配置来指定持久化文件的名字。 appendfilename append.aof
AOF 的实现
AOF
会通过保存客户端发送的通讯协议进行保存,所以会导致 AOF
文件越来越大的问题,因为可能出现的情况是,一个键被设置了,后面又被删除了,这时候完全可以不进行记录这一个过程。那么可以通过配置文件来设置 redis
当 AOF
文件达到一定容量的时候进行 AOF
的优化重写:
1 | auto-aof-rewrite-percentage 100 # 当前 AOF 文件超过上一次的 AOF 文件的百分之多少时进行重写,如果无重写过则以启动时的文件大小为准 |
除了可以让 redis
自动重写以外,还可以通过传输命令 BGREWRITEAOF
来触发 redis
的重写。
同步硬盘数据
虽然每次都会重写 AOF
文件,但是此时这个文件并没有真正的写入硬盘中,而是进入硬盘缓存,如果此时系统出现异常宕机,则会导致数据的丢失。系统默认情况下,30秒执行一次同步硬盘操作,但是一般开启 AOF
的应用都不能允许这个情况的出现,这就需要 redis
在写入 AOF
文件的时候,主动触发同步硬盘。我们可以通过以下设置来实现这个目的:
1 | aapendfsync everysec # 每秒执行一次同步操作,也是默认设置 |
可选值:always
no
前者是每次写入 AOF
都进行同步,后者则完全交由系统决定。
持久化使用
redis
允许同时开启两种模式,既保证数据安全又使得备份十分容易。重启 redis
后 redis
会使用 AOF
方式来回复数据,因为 AOF
可能丢失的数据更少。