Loading

Redis的持久化机制

持久化机制

进行持久化的方式:

  • AOF日志:每执行一条写操作的命令,就把该命令以追加的方式写入到一个文件里。
  • RDB快照:将某一时刻的内存数据以二进制的方式写入磁盘
  • 混合持久化方式:集成了AOF和RDB的优点
AOF日志

img

先执行命令再写日志的优缺点

优点:

  • 避免了额外的检查开销:因为是在执行成功后才写日志,所以能写日志则说明可以通过语法检查,避免了再单独检查。
  • 不会阻塞当前写操作命令的执行:因为当写操作命令执行成功后才会将命令记录到AOF日志中

缺点:

  • 数据可能会丢失:因为写操作命令和记录日志是两个过程,可能会出现写完操作命令还没来得及日志写磁盘宕机丢失。
  • 可能会阻塞其他操作:虽然是在写完命令操作后再写日志,不会阻塞写操作命令,但是由于也是在主线程中执行,可能会阻塞后续的操作。

AOF日志执行过程

image-20230813211243793

  1. redis执行完写命令操作后,会将命令追加到server.aof_buf缓冲区
  2. 调用write将aof_buf缓冲区的数据写入到AOF文件,此时处于page cache,等待内核将数据写入硬盘
  3. 具体内核缓冲区写入硬盘的时机由内核决定。

写回策略:

  • Always:每次写操作命令执行完后都同步将AOF日志写回硬盘
  • Everysec:每次写操作命令执行完后先将命令写入到AOF文件的内核缓冲区,然后每隔一秒将缓冲区里的内容写回到硬盘
  • No:每次写操作命令执行完后,先将命令写入到 AOF 文件的内核缓冲区,再由操作系统决定何时将缓冲区内容写回硬盘。

重写机制:

为了避免AOF日志越写越大,Redis提供了重写机制,当AOF大小超过了阈值就会重写。

在重写时,读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到新AOF文件中,全部记录完后替换掉旧文件。

由后台子进程 bgrewriteaof完成

  • 子进程在进行AOF重写时,主进程仍然可以继续处理命令请求,不会被阻塞。
  • 用子进程避免了用线程时需要加锁的情况,不会降低性能。使用子进程可以共享物理内存,但是是只读的。不需要进行加锁

重写过程中,主进程仍然处理命令操作,此时主进程若修改已经存在的KV数据则会发生写时复制,为了解决这个问题redis设置了AOF写缓冲区,重写AOF期间Redis每写完一个命令后会同时将这个写命令写入到AOF缓冲区AOF重写缓冲区中。当子进程完成重写后会给主进程发一条信号,主进程收到信号后会调用一个信号处理函数:

  • 将AOF重写缓冲区的内存追加到新AOF文件
  • 将新的AOF文件改名并覆盖现有的AOF文件
RDB快照

记录了某一瞬间的内存数据,是全量快照,把内存中的所有数据都记录到磁盘中。redis恢复数据时用RDB恢复效率更高。不需要执行AOF里的命令。

生成RDB快照

提供了两个命令来生成RDB文件

  • save:在主线程中生成RDB文件,如果写入RDB文件时间太长会阻塞主线程
  • bgsave:创建一个子进程来生成RDB文件,避免阻塞主线程

redis还可以通过配置文件的选项实现每隔一段时间自动执行一次bgsave

image-20230813214755309

  • 900秒内对数据库进行了至少1次修改
  • 300秒内对数据库进行了至少10次修改
  • 60秒内对数据库进行了至少10000次修改

执行快照时修改数据

在执行bgsave时仍然可以继续处理操作命令,关键在于写时复制

在执行bgsave命令时会创建子进程,与父进程共享同一片内存数据,因为创建子进程时会复制父进程的页表,但页表指向的物理内存还是一个,若主线程执行写操作,则被修改的数据会复制一份副本然后bgsave子进程会把该副本写入RDB文件,过程中主进程仍然可以直接修改原来的数据。

混合持久化

使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据

优点:

  • 结合了RDB和AOF的优点,开头为RDB格式,使得Redis可以更快的启动,同时结合了AOF的优点,降低了大量数据丢失的风险

缺点:

  • AOF文件中添加了RDB格式,文件可读性变差。
  • 兼容性差,不能用在Redis4.0之前版本。
posted @ 2023-09-26 15:33  墨鱼yyyl  阅读(14)  评论(0)    收藏  举报  来源