Redis持久化


前言

因为Redis是内存数据库,它将自己的数据库状态存储在内存里面,所以如果不想办法将存储在内存中的数据库状态保存到磁盘里面,那么一旦服务器进程退出,服务器中的数据库状态也会消失不见。
Redis为了解决这个问题,提供了两种持久化方式。一种是RDB,另一种是AOF方式。前者会根据规则“定时”将内存中的数据保存储在磁盘上,而后者在每次执行命令后将命令的本身记录下来。


一、RDB持久化

RDB持久化是通过快照(snapshoting)完成的,当符合一定的条件时,Redis会自动将内存中的数据保存到磁盘上。Redis会在以下几种情况下对Redis进行快照:

  1. 执行save命令:save命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器阻塞期间,服务器不能处理任何命令请求。
  2. 执行bgsave命令:会调用glbc的函数fork产生一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求。
  3. 自动间隔性保存:因为bgsave命令可以在不阻塞服务器进程的情况下执行,所以Redis允许用户通过设置服务器配置的save选项,让服务 器每隔一段时间自动执行一次bgsave命令。
    比如我们在服务器配置如下:
    save 900 1
    save 300 10
    save 60 10000
    那么只要满足以下三个条件中的任意一个,Bgsav命令就会被执行:
    服务器在900秒以内,对数据库进行了至少1次修改。
    服务器在300秒以内,对数据库进行了至少10次修改。
    服务器在60秒以内,对数据库进行了至少10000次修改。
  4. 执行FLUSHALL命令:Redis Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。执行该命令也会生成Rdb文件。
  5. 执行复制(replication)时。
  6. Redis停机时。

二、AOF持久化

AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。
为了提高文件写入效率,在现代操作系统中,当用户调用write函数,将一些数据写入到文件的时候,操作系统通常会将写入数据暂时保存在一个内存缓冲区里面,等到缓冲区的空间被填满,或者超过了指定的时限之后,才真正地将缓冲区中的数据写入到磁盘里面。

1.如何保证写入数据的安全性

缓冲区这种做法虽然提供了效率,但是也为写入数据带来了安全问题,因为如果计算机发生停机,那么保存在内存缓冲区里面的写入数据将会丢失。

为此,系统提供了fsync和fdatasync两个同步函数,它们可以强制让操作系统立即将缓冲区中的数据写入到硬盘里面,从而确保写入数据的安全性。

Redis提供的AOF配置项appendsync写回策略直接决定AOF持久化功能的效率和安全性。

  1. 当appendsync 的值为always时,服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件,并且同步AOF文件,所以always的效率是appendsync选项三个值当中最慢的一个,但从安全性来说,always也是最安全,因为即使出现故障停机,AOF持久化也只丢失一个事件循环中所产生的命令数据。
  2. 当appendsync的值为everysec时,服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件,并且每隔一秒就要在子进程中对AOF文件进行一次同步。所以从效率上来讲,everysec模式足够快,并且就算出现故障停机,数据库也只丢失一秒中的命令数据。
  3. 当appendsync的值为no时,服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件,至于何时对AOF文件进行同步,则由操作系统控制。

所以想要获得⾼性能,就选择 No 策略; 如果想要得到⾼可靠性保证,就选择 Always 策略;如果允许数据有⼀点丢失,⼜希望性能别受太⼤影响的话,那 么就选择 Everysec 策略。

2.如何解决AOF文件体积问题

因为AOF持久化是通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行事件的流逝,AOF文件中的内容会越来越多,文件的体积也会越来越大。

为了解决AOF文件体积膨胀的问题,Redis提供了AOF文件重新功能。通过该功能,Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件。

AOF文件重写并不需要对现有的AOF文件进行任何读取,分析或者写入操作,这个功能是通过读取服务器当前的数据库状态来实现的。
比如服务器对list键执行了以下命令:
RPUSH list “A” “B”
RPUSH list “C”
RPUSH list “D” “E”
LPOP list
LPOP list
RPUSH list “F” “G”

正常情况下需要在AOF文件中写入六条命令。而为了减少AOF文件中的命令数量,首先从数据库中读取键现在的值,然后用一条命令区记录键值对,代替之前记录这个键值对的多条命令,这就是AOF重写功能的实现原理。比如上面这个合并成一条命令为:
RPUSH list “C” “D” “E” “F” “G” 来代替保存在AOF文件中的六条命令。

命令合并又会带来一个新的问题,比如重写程序在处理列表,哈希表,集合,有序集合这四种可能带有多个元素的键时,假设合并后命令太长,那么就会造成客户端输入缓冲区溢出。AOF重写是如何解决这个问题的呢?

在重写之前,会先检查键所包含的元素数量,如果超过了64个元素,那么重写程序会多条命令来记录,并且每条命令设置的元素数量也为64个。
AOF重写数据的一致性:
在重写AOF文件的时候,为了避免客户端阻塞,Redis将AOF重写程序放到子进程里执行,这样可以达到两个目的:
子进程进行AOF重写期间,服务器进程(父进程)可以继续处理命令请求。
子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。

3.如何解决AOF重写期间数据的一致性

不过使用子进程也有一个问题需要解决,因为子进程在进行AOF重写期间,服务器进程还需要继续处理命令请求,而新的命令可能会对现有的数据库状态进行修改,从而使的服务器当前的数据库状态和重写后的AOF文件所保存的数据库状态不一致。

为了解决这种数据不一致的问题,Redis服务器设置了一个AOF重写缓冲区。

在子进程进行AOF重写期间,如果服务器执行了相应的写命令,会吧这些写命令都记录到AOF重写缓冲区里。当子进程完成AOF重写工作之后,它会向父进程发送一个信号,父进程在接到该信号之后,将AOF重写缓冲区中所有的内容写入到AOF文件中,这时新AOF文件所保存的数据库状态将和服务器当前的数据库状态一致。

三、RDB和AOF优缺点

RDB
优点:
• RDB快照是一个压缩过的非常紧凑的文件,保存着某个时间点的数据集,适合做数据的备份,灾难恢复;
• 可以最大化Redis的的性能,在保存RDB文件,服务器进程只需要fork一个子进程来完成RDB文件的创建,父进程不需要做IO操作;
• 与AOF相比,恢复大数据集的时候会更快;
缺点:
• RDB的数据安全性是不如AOF的,保存整个数据集的过程是比繁重的,根据配置可能要几分钟才快照一次,如果服务器宕机,那么就可能丢失几分钟的数据;
• Redis数据集较大时,fork的子进程要完成快照会比较耗CPU、耗时;
AOF
优点:
• 数据更完整,安全性更高,秒级数据丢失(取决fsync策略,如果是everysec,最多丢失1秒的数据);
• AOF文件是一个只进行追加的日志文件,且写入操作是以Redis协议的格式保存的,内容是可读的,适合误删紧急恢复;
缺点:
• 对于相同的数据集,AOF文件的体积要大于RDB文件,数据恢复也会比较慢;
• 根据所使用的fsync策略,AOF的速度可能会慢于RDB。 不过在一般情况下,每秒fsync的性能依然非常高;

四、RDB和AOF如何选择

通常来说,应该同时使用两种持久化方案,以保证数据安全。
• 如果数据不敏感,且可以从其他地方重新生成,可以关闭持久化。
• 如果数据比较重要,且能够承受几分钟的数据丢失,比如缓存等,只需要使用RDB即可。
• 如果是用做内存数据,要使用Redis的持久化,建议是RDB和AOF都开启。
• 如果只用AOF,优先使用everysec的配置选择,因为它在可靠性和性能之间取了一个平衡。
当RDB与AOF两种方式都开启时,Redis会优先使用AOF恢复数据,因为AOF保存的文件比RDB文件更完整

五、Redis 4.0 混合日志模型

重启 Redis 时,我们很少使用rdb 来恢复内存状态,因为会丢失⼤量数据。我们通常使⽤ AOF ⽇志重放,但是重 放 AOF ⽇志性能相对 rdb 来说要慢很多,这样在 Redis 实例很⼤的情况下,启动需要花费很⻓的时间。
Redis 4.0 为了解决这个问题,带来了⼀个新的持久化选项——混合持久化。将 rdb ⽂件的内容和增量的 AOF ⽇志 ⽂件存在⼀起。这⾥的 AOF ⽇志不再是全量的⽇志,⽽是⾃持久化开始到持久化结束的这段时间发⽣的增量 AOF ⽇志,通常这部分 AOF ⽇志很⼩。 于是在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF ⽇志就可以完全替代之前的 AOF 全量⽂ 件重放,重启效率因此⼤幅得到提升。 所以 RDB 内存快照以稍微慢⼀点的频率执⾏,在两次 RDB 快照期间使⽤ AOF ⽇志记录期间发⽣的所有「写」操 作。 这样快照就不⽤频繁的执⾏,同时由于 AOF 只需要记录两次快照之间发⽣的「写」指令,不需要记录所有的操 作,避免出现⽂件过⼤的情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一些关于 Redis 持久化的可能面试问题: 1. Redis持久化有哪些方式? Redis持久化有两种方式,一种是 RDB 持久化,一种是 AOF 持久化。 2. RDB 持久化和 AOF 持久化有什么区别? RDB 持久化是将 Redis 在内存的数据快照保存到磁盘上,而 AOF 持久化则是将 Redis 执行的每条写命令记录到磁盘上。RDB 持久化可以节约磁盘空间,但可能会丢失最近的一些数据,而 AOF 持久化可以保证数据不会丢失,但可能会占用更多的磁盘空间和写入时间。 3. Redis持久化机制是如何保证数据一致性的? Redis持久化机制可以通过在每次写操作后立即同步到磁盘,或者设置定期同步时间来保证数据一致性。 4. Redis持久化可以在运行时进行吗? 可以,Redis持久化可以在运行时进行配置和切换,例如可以在运行时从 RDB 切换到 AOF 持久化,或者从 AOF 切换到 RDB 持久化。 5. Redis持久化会对性能产生影响吗? 会,Redis持久化会增加磁盘 I/O 开销,可能会对写入性能产生一定的影响,但可以通过合理的配置来平衡性能和数据一致性。 6. Redis持久化可以与 Redis 集群一起使用吗? 可以,Redis持久化可以与 Redis 集群一起使用,但需要注意配置文件的设置和数据同步的策略。 总之,Redis持久化是保证数据一致性和可靠性的重要手段,需要根据具体的业务需求和性能要求来选择合适的持久化方式,并进行合理的配置和优化。在面试,还需要了解 Redis 持久化的原理、机制、优缺点、与集群的结合等方面的知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值