Redis持久化详解,RDB与AOF比较分析

文章目录

  • 一、RDB(Redis DataBase)
  • 二、AOF(Append Only File)
    • 文件重写:
    • 为什么使用的是子进程而不是子线程?
  • 三、AOF与RDB混合使用
  • 四、配置文件选项解析
  • 五、RDB与AOF优劣与分析
    • 1.RDB优劣
    • 2.AOF优劣
    • 3.二者选择

        redis是内存数据库,如果没有持久化,那么数据断电即失。对于持久化的文件,如果受损了,redis会自动尝试修复,当提示无法修复的时候,可以使用执行 redis-check-aof --fix appendonly.aofredis-check-rdb --fix dump.rdb进行修复,出现错误的数据会被丢弃。

一、RDB(Redis DataBase)

        在指定时间间隔内将内存中的 数据集快照写入磁盘,也就是Snapshot快照,它恢复时是将快照文件直接读到内存里。
Redis持久化详解,RDB与AOF比较分析_第1张图片
        Redis的自动保存为BGSAVE操作,Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件,用二进制压缩存储(binlog)。fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程,也就是说在fork会将内存瞬间增大一倍。整个过程,主进程是不会进行任何IO操作的。这就确保了极高的性能。如果需要大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更高效。RDB的缺点是最后一次持久化后的数据可能丢失。redis默认使用RDB。

自动触发机制:
        在配置文件中我们可以看到改字段,其含义为在900秒内存在1次修改时,自动触发BGSAVE。后面含义与此类似。
Redis持久化详解,RDB与AOF比较分析_第2张图片
        持久化产生的默认文件名为dump.rdb

注意:

  • 一般来说,在生产环境很少执行 SAVE操作,SAVE直接调用rdbSave,阻塞Redis主进程,直到保存完为止,在主进程阻塞期间,服务器不能处理客户端任何请求。所以一般使用BGSAVE异步地执行,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。如果负责保存数据的后台子进程不幸出现问题时,SAVE可以作为保存数据的最后手段使用。Redis持久化详解,RDB与AOF比较分析_第3张图片
  • 如果执行shutdown命令关闭服务器,会在后台执行save命令对数据进行持久化。使用shutdown nosave则不会产生该文件
  • 使用flushall命令清除也会产生dump.rdb文件,但其内容为空

        如果要恢复rdb文件,只需要将rdb文件放在redis启动目录即可,redis启动时就会自动检查dump.rdb 恢复其中的数据,可使用config get dir 查看dump.rdb文件读取位置,也可在配置文件中自行配置。

二、AOF(Append Only File)

        将我们所有的命令全都记录下来(读操作不记录),history,恢复时就把这个文件中的命令全部执行一遍。(默认不开启AOF功能,若其与RDB同时开启,优先使用AOF,因为其恢复数据更全)
Redis持久化详解,RDB与AOF比较分析_第4张图片        以日志形式来记录每个写操作,redis会将每一个收到的写命令都通过write函数追加到文件中(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构造数据,换而言之,redis重启后就会将该文件中的内容,将写指令从头到尾执行一次以完成数据恢复工作。

自动触发机制:
        AOF也有三种触发机制:每修改同步always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好。每秒同步everysec:异步操作,每秒记录 如果一秒内宕机,有数据丢失。不同步no:从不同步
Redis持久化详解,RDB与AOF比较分析_第5张图片Redis持久化详解,RDB与AOF比较分析_第6张图片
        持久化产生的默认文件名为appendonly.aof

文件重写:

        AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。为了压缩aof的持久化文件。redis提供了BGREWRITEAOF命令主动进行重写,也可以在文件超过64mb(默认)时也会自动重写。

  1. Redis会使用到操作系统提供的 fork() 方法创建子进程来完成复制操作。
    fork子进程时,有两种情况会阻塞主进程

    • 创建子进程的途中,复制父进程的页表等数据结构,有了父进程内存数据的映射,指向相同的内存地址,也能共享父进程的内存数据
    • 发生写操作的时候,操作系统才会去复制物理内存,这样可以防止fork子进程时复制资源时间过长导致主进程阻塞,若发送写时复制,主进程阻塞是不可避免地。
  2. 直接把当前内存的数据生成对应命令,并不需要读取老的AOF文件

  3. 在重写期间,由于主进程依然在响应命令,为了保证最终备份的完整性;因此它依**然会写入旧的AOF file中,如果重写失败,能够保证数据不丢失。**期间主进程需要执行以下三个工作:

    • 父进程继续执行客户端发来的命令;
    • 父进程将执行后的写命令追加到 「AOF 缓冲区」
    • 父进程将执行后的写命令通过管道追加到子进程的 「AOF 重写缓冲区」(这个过程中会使正常用户请求延时变高);
  4. 子进程完成后通知父进程,父进程进行下面操作:

    • 将 AOF 重写缓冲区中的所有内容追加到新的 AOF 的文件中,使得新旧两个 AOF 文件所保存的数据库状态一致;
    • 新的 AOF 的文件进行rename,覆盖现有的 AOF 文件。

为什么使用的是子进程而不是子线程?

        子进程带有主进程的数据副本,这里使用子进程而不是线程,因为如果是使用线程,多线程之间会共享内存,那么在修改共享内存数据的时候,需要通过加锁来保证数据的安全,而这样就会降低性能。而使用子进程,创建子进程时,父子进程是共享内存数据的,不过这个共享的内存只能以只读的方式,而当父子进程任意一方修改了该共享内存,就会发生「写时复制」,于是父子进程就有了独立的数据副本,就不用加锁来保证数据安全。

三、AOF与RDB混合使用

配置文件配置aof-use-rdb-preamble yes来开启混合使用

  • 两者同时使用时,优先使用AOF恢复数据,没有AOF文件才会使用RDB恢复
  • 如果RDB在保存快照时,redis不会AOF重写; 如果AOF重写时,就不会执行RDB快照,防止两种持久化方式争抢资源。
  • AOF文件:混合持久化时会将内存中数据进行RDB快照处理,然后与期间产生的增量指令一起存入aof文件中,此时aof文件的前半部分是二进制形式,后半部分是指令新式,查看文件时会发现前面是乱码,后面是可读指令。是为了更快的恢复数据

四、配置文件选项解析

1.snapshotting快照 rdb配置

save 900 1 #若900秒内,至少有一个key进行了修改,就进行持久化
save 300 10 #同上
save 60 10000 #同上,高并发

stop-writes-on-bgsave-error yes 
#持久化出错,redis是否停止接收数据,使用户意识到数据并未正确持久化到磁盘上。

rdbcompression yes
#对于存储到磁盘中的快照即dump.rdb,可以设置是否进行压缩存储。

rdbchecksum yes 
#在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。

dbfilename yes 
#设置快照的文件名,默认是 dump.rdb

dir ./
#rdb文件保存的目录,不能是文件名

2.append only模式 aof配置

appendfsync everysec #同步
#always 每次修改都会sync,消耗性能
#everysec 每秒执行一次sync,如果宕机,则会丢失这一秒数据
#no 不同步,这时候操作系统自己同步数据,速度最快

no-appendfsync-on-rewrite no  
#默认为no是最安全的方式,不会丢失数据,但在大量磁盘操作时会出现阻塞问题的问题。
#若设置为yes不会执行磁盘操作,只是写入了缓冲区,因此不会造成阻塞(因为没有竞争磁盘),但若此时redis挂掉,在linux的默认设置下,最多会丢失30s的数据。

auto-aof-rewrite-percentage 100 
#文件的大小超过基准百分之多少后触发bgrewriteaof。
#默认这个值设置为100,意味着当前aof是基准大小的两倍的时候触发bgrewriteaof。把它设置为0可以禁用自动触发的功能。

auto-aof-rewrite-min-size 64mb 
#当文件大小超过64mb时候就会重写aof文件

五、RDB与AOF优劣与分析

1.RDB优劣

(1)优势

  1. RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑,非常适合用于进行备份和灾难恢复。
  2. 生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
  3. RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

(2)劣势

  1. 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
  2. 当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。

2.AOF优劣

(1)优势

  1. AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。
  2. AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
  3. AOF日志文件即使过大的时候,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。同时也不会影响客户端的操作。
  4. AOF对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容
  5. AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据

(2)劣势

  1. 对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
  2. AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的

3.二者选择

        根据自己需求,是否愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。在两者同时启用时,AOF的优先级更高,因为其保存的数据更加完整。
Redis持久化详解,RDB与AOF比较分析_第7张图片
性能建议:

  1. 只做缓存,如果希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化
  2. 因为RDB文件只做后备用用途,建议只在Slave上持久化RDB文件,且只要15分钟备份一次就够了,只保留save 900 1这条规则
  3. 如果开启 AOF,好处是在最恶劣的情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了,代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认64M太小了,可以设置到5G以上,默认超过原大小100%大小重写可以改到适当数值
  4. 如果不关闭 AOF,仅靠Master-Slave Replication(主从复制)实现高可用性也可以,能省掉一大笔IO,也减少了rewrite时带来的系统波动。代价是如果Master/Slave 同时宕机,如断电,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。

你可能感兴趣的:(Redis,数据库,Java进阶,redis,linux,nosql)