Redis持久化

RDB
RDB是通过直接将K-V键值对保存在硬盘文件来持久化。
  • 通过两个命令可以让服务器执行rdb操作(tips:SAVE和BGSAVE底层都是调用的rdbSave)
    • SAVE:SAVE命令由主进程执行,所以当执行SAVE命令后,服务器将进入阻塞状态,只有当RDB文件生成完成后,才开始处理请求。
    • BGSAVE:BGSAVE的RDB文件是fork出一个子进程来执行SAVE操作,此时redis服务器是非阻塞仍旧可以继续处理接受请求。
    • 但是BGSAVE命令执行期间,服务器处理SAVE,BGSAVE,BGREWRITEAOF三个命令的方式会有所不同。
      • SAVE:命令会被拒绝,服务器为了避免父子进程同时执行两个rdbSave调用,防止产生竞争条件。
      • BGSAVE:理由同上。
      • BGREWRITEAOF:不能同时执行,必须等一个先执行完了另一个才开始执行,这是从性能方面考虑,两个子进程同时执行大量的磁盘写入操作,影响性能。
  • RDB文件没有手动载入的命令,服务器启动时会主动去读取RBD文件,同样在RDB文件载入时,服务器处于阻塞状态。
  • 定时BGSAVE:设置参数让redis服务器定时生成RDB文件:
    • save 900 1:900秒内有一次修改就生成,该配置项保存在server.saveparams中,redis的定时维护任务serverCron每隔100毫秒检查一次saveparams中的参数,如果满足就执行BGSAVE。
  • RDB文件格式和分析这里就不赘述了,参考redis设计与实现第二版
AOF
AOF是将服务器接收到的命令保存在硬盘文件上来实现持久化。
  • redis服务器的进程就是事件循环,这个循环中的文件事件负责接受客户端的请求,并回复,而时间事件则负责执行像serverCron这样需要定时运行的函数。
  • 服务器在执行对数据库有修改的操作的时候会将命令存储到aof_buf里,所以服务器在每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函数,考虑是否将aof_buf缓冲区的内容写入和保存到AOF文件里。
    • flushAppendOnlyFile的行为由服务器配置项appendfsync控制
      1. always:将所有命令都持久化到文件中。
      2. everysec:每秒更新,这是一个单独的线程控制的。(这是默认值)
      3. no:不将aof_buf中的刷新到aof文件中,什么时候刷新由系统自己决定。
    • 此外还有个操作系统导致的数据不安全问题,当redis服务器要将缓冲中的命令刷新到AOF文件里时,操作系统执行write操作时,会将数据先写入write缓冲中,等到缓冲被填满或者超过指定时限后才刷入硬盘,redis为了解决这个问题提供了两个函数,fsync和fdatasync来强制让操作系统立即将数据写入硬盘文件。
  • redis从aof恢复:redis服务器会开启一个不带网络连接的fake client,由于redis命令只能由客户端发起,所以开启一个假客户端来不断发送aof文件里的命令,由服务器执行,全部完成后服务器即恢复。
  • AOF文件重写功能:
    • 目的:为了解决不断累加的AOF文件过大的问题。
    • 原理:aof_rewrite不会去分析或者载入曾经的AOF文件,而是直接读取数据库中的数据生成最少的命令加入到新的AOF文件里。
    • aof_rewrite也由子进程执行。
    • 在子进程进行rewrite操作的时候,客户端还会不断有命令进来,此时可能会导致数据库状态的不一致,redis为了解决这个问题会将在这期间接受到的命令同步发送给aof_buf和aof_rewrite_buf,当rewrite完成后子进程会发送一个信号通知父进程,父进程在接收到该信号之后会将aof_rewrite_buf中的命令写到新的AOF文件里,同时完成新旧AOF文件的替换(原子操作)。 

相关推荐