Redis 持久化机制

时间:2023-01-03 15:52:16

个人博客地址:

Redis 持久化机制

1. 概述

Redis​为了保证性能,会将所有数据放在内存中,那么万一Redis宕机,数据岂不是全部丢失了?

不要怕,Redis自然想到了这一点,它提供了三种持久化机制将内存中的数据持久化到磁盘中。

  1. RDB

    快照方式持久化(snapshot),快照在Linux就已经学过,保存所有数据的状态,下次开机直接按照这个状态恢复。

    因为保存的快照是以.rdb结尾的文件,故称此方式为RDB持久化方式。

  2. AOF

    (append only file)只追加日志文件,记录Redis所有写命令,下次开机将这些命令全部执行,即可恢复数据。

  3. 混合型持久化

    RDB虽然快,但是数据丢失问题较为严重;AOF虽然能保证数据安全,但是执行所有命令需要很长时间。

    所以Redis4.x以后,将两种方式结合,RDB文件的内容放在AOF文件中,以.aof文件的形式存储。在恢复数据时,先加载rdb的内容,再执行aof的内容。缺点是两种格式混合在一起难以阅读。

需要注意的是,不论是哪种方式,都无法保证数据的绝对安全。

2. RDB

snapshot想必大家已经不陌生了,Linux已经接触过这个机制:保存现在的状态,随时准备恢复。

拍摄的快照以**.rdb**的形式保存在磁盘中。

假如在Redis宕机之前拍摄的快照为:
Redis 持久化机制
那么下次开机就可以即将这两个数据恢复。

Redis提供了两种拍摄快照的方式 :自动、手动。其中手动拍摄快照有两个命令:save、bgsave
Redis 持久化机制

2.1 手动快照

  1. save

    由主进程完成快照的拍摄,持久化过程中其他命令阻塞。
    Redis 持久化机制

  2. bgsave
    background save,主线程fork出一个子进程,由这个子进程完成持久化。

    Redis 持久化机制

fork :

当一个进程创建子进程时,底层的操作系统会创建该进程的副本,在类unix系统中创建子进程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程/子进程对内存进行写操作后结束共享,各用各的。

2.2 自动快照

在redis.conf配置文件中存在,参数如下:(版本不同,默认参数不同)

#   * After 3600 seconds (an hour) if at least 1 key changed
#   * After 300 seconds (5 minutes) if at least 100 keys changed
#   * After 60 seconds if at least 10000 keys changed

# save 3600 1
# save 300 100
# save 60 10000

解释 :

1h内有一个键被改变会触发快照拍摄。

5mins内有100个键被改变会触发快照拍摄。

1min内有10000个键被改变会触发快照拍摄。

这些快照的拍摄方式都是bgsave。

优点 :

  • rdb文件的加载速度特别快,远超aof。

  • 使用单独子进程来进行持久化,主进程不会进行任何 IO 操作。

缺点 :

  • 容易造成数据丢失。

  • 每次拍快照都要创建子进程,浪费资源.。

3. AOF

这种机制可以将所有客户端执行的写命令记录到日志文件中,AOF​持久化会将被执行的写命令写到AOF文件末尾,以此来记录数据发生变化的全过程,因此只要Redis从头到尾执行一遍AOF文件中的命令,就可以恢复之前的数据。

3.1 AOF机制

RDB​是间隔一段时间进行持久化,如果持久化之间的时间内发生故障,会出现数据丢失。而AOF​持久化方式能很好的解决RDB​持久化方式造成的数据丢失,AOF​持久化到硬盘中的并不是内存中的数据快照,而是将所有写命令记录到日志中

AOF能做到最多丢失1s内的数据,甚至不丢失数据。

Redis提供了三种AOF策略 :

  • appendfsync always

    每执行一次写命令,都对aof文件续写。

  • appendfsync everysec

    每一秒进行一次aof文件续写,这一秒的写命令都会记录。

  • appendfsync no

    并不是不开启,而是将aof续写的时机交给操作系统管理,操作系统开心了就续写,不开心就不续写。

优点 :

  • 保证数据丢失风险降到最低

缺点 :

  • aof文件的体积会很大,同时加载速度很慢

3.2 AOF文件的重写

随着Redis​在线上运行的时间越来越久,客户端执行的命令越来越多,AOF​的文件也会越来越大。

当我们执行100次set name 张三​,其中99次都是多余的,因为想要恢复只要执行一次set name 张三​就行了。为了压缩AOF文件的体积,Redis提供了AOF文件重写机制​。

有两种方式触发AOF的重写机制:

  • 手动:执行bgrewrite​,background rewrite,不会阻塞Redis

  • 自动:在配置文件中进行配置

    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    

    当AOF文件体积大于64MB,或者比上一次重写之后体积大了100%,会自动触发。

    如果重写过于频繁,可以考虑将auto-aof-rewrite-percentage设置为更大。

重写的原理 :

重写AOF文件的操作并不是基于原本的AOF文件,而是讲真个内存中的数据库内容用命令的方式重写了一个新的AOF文件,替换原有的AOF文件,这样可以避免一些无用的命令。

4. 混合型持久化

因为RDB​虽然加载快但是存在数据丢失,AOF​数据安全但是加载缓慢,Redis​为了解决这个问题,带来了一个新的持久化选项——混合持久化。将RDB​文件的内容和增量的AOF​日志文件存在一起。这里的AOF​日志不再是全量 的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF​日志,通常这部分AOF​日志很小。Redis​重启的时候,可以先加载RDB​的内容,然后再重放增量AOF​日志,就可以完全替代之前的AOF​全量文件重放,恢复效率因此大幅得到提升(混合型持久化最终生成的文件后缀是.aof​,可以通过redis.conf​文件中aof-use-rdb-preamble yes​配置开启)。

  • 优点:

    结合了RDB​和AOF​的优点,使得数据恢复的效率大幅提升

  • 缺点:

    兼容性不好,Redis-4.x​新增,虽然最终的文件也是.aof​格式的文件,但在4.0​之前版本都不识别该aof​文件,同时由于前部分是RDB​格式,阅读性较差。

5. 总结

Redis 持久化机制