获取中...

-

Just a minute...

什么是AOF持久化

Redis有两种持久化方式,RDB和AOF。RDB是将Redis中的数据保存一份到RDB文件中,而AOF不是保存键值对数据,而是保存服务器执行的写命令来记录数据库的状态。

AOF持久化的实现原理

AOF持久化的实现可以分为三个步骤:命令追加、文件写入、文件同步。

命令追加

当Redis的AOF持久化功能打开之后,服务器在执行完一个写入命令后,将会以协议格式将被写入的命令追加到服务器的aof_buf缓存区的末尾。打开AOF持久化的设置在redis.conf中,配置项如下:

1
2
# 默认是没有打开的,设置为yes则为打开状态
appendonly no
文件写入和同步

服务器每次结束一个事件循环之前,服务器就会调用flushAppendOlnyFile函数,判断是否需要将aof_buf中的内容写入AOF文件中。flushAppendOlnyFile函数会根据Redis服务器配置文件中appendfsync的值做不同的处理,配置项在redis.conf中,如下:

1
2
#默认为everysec 可选值还有no、always
appendfsync everysec

每一个值的含义如下:

  • no:将aof_buf中的所有内容写入AOF文件,但不对AOF文件进行同步,何时同步需要操作系统决定。
  • everysec:将aof_buf中的所有内容写入AOF文件,如果上次同步AOF文件的时间距离现在超过一秒,那么再次对AOF文件进行同步,同步的操作由一个线程专门负责执行。
  • always:将aof_buf中的所有内容写入AOF文件并同步AOF文件。
    不管是哪一种选项,都会将aof_buf缓存区中的内容写到AOF文件中,但是同步的时机不一样,这主要和文件的写入和同步在操作系统中有关。

关于操作系统中文件的写入和同步:为了提高文件的写入效率,现代计算机操作系统中,当用户调用write函数的时候,会将数据先写入一个缓存区中,等缓存区的大小超过限制或被填满后,才会真正的同步到磁盘中。这种做法虽然高效,但如果在数据写入缓存区但还没有同步到磁盘的时候,计算机停机将会丢失数据。所以操作系统提供了fsync和fdatasync两个同步函数强制同步缓存区中的数据到磁盘中。

AOF文件的载入和数据还原

AOF文件中有所有重建数据库数据的写入命令,只需要将命令重新执行一遍即可。具体实现为:由于Redis的写入命令是需要从客户端执行的,所以服务端会创建一个伪客户端,负责执行AOF中的命令。伪客户端将把AOF中的命令一条条的读取出来执行,直到所有的命令执行完成。

AOF重写

由于AOF是通过保存写入命令来实现持久化的,每次写入的命令都会存到文件中,随着时间的流逝,AOF文件会越来越大,以至于AOF文件载入的时候非常的耗时。所以Redis提供了一个AOF重写的功能,使用重写后的文件来代替原来的AOF文件。

重写的原理

Redis会从数据库中读取键现在的值,然后使用一条命令保存这个值,这样就可以保存所有的key的最新的值,并且减小AOF的大小。

AOF后台重写

由于重写是比较耗时的,所以Redis将重写的功能放在一个子进程中,这样主进程还可以继续处理客户端的请求。但是,由于在子进程在重写的期间,主进程还在接受写的操作,可能会修改正在重写的数据,造成数据不一致,所以Redis设置了一个重写缓冲区。当Redis服务器执行完一个写命令的时候,会同时将该命令写入AOF缓冲区和AOF重写缓冲区。当进行重写的时候,Redis启用子进程进行AOF重写,Redis服务器继续处理客户端的请求,并将写入的命令放入两个缓冲区中。当子进程完成AOF重写,会向父进程发送一个信号,父进程接收到信号后会调用一个信号处理函数,将AOF重写缓冲区中的数据同步到AOF文件中,并原子性的用新的AOF文件替代旧的AOF文件。整个过程中只有在信号处理函数在处理的时候会阻塞服务器进程。这个就是BGREWRITEAOF命令的实现原理。

相关文章
评论
分享
  • Redis过期策略和内存淘汰策略

    Redis处理过期的keyRedis会将每个设置了过期时间的key保存在一个独立的字典中,以后会定期扫描这个字典来删除过期了的key。除了定期扫描删除策略之外,Redis同时采用惰性删除策略,在客户端访问key的时候,Redis会对这...

    Redis过期策略和内存淘汰策略
  • Redis持久化:RDB

    什么是RDB持久化RDB持久化是Redis的持久化方式之一,也被称为快照持久化,是将某一个时间节点的Redis内存中数据保存到磁盘上,生成一个RDB文件。之后,用户可以将这份文件进行备份,复制到其他的服务器上创建具有相同状态的Redi...

    Redis持久化:RDB
  • jps命令详解

    jps命令的作用jps命令是JDK中自带的命令,位于bin目录下,其作用是显示当前用户下系统中所有的Java进程的相关信息,比如pid。有了这个命令,可以很方便的显示Java进程,不过显示的是当前用户的所有Java进程,不能根据项目名...

    jps命令详解
  • Java多线程之同步容器

    同步容器的作用Java中的容器主要为List、set、Map、Queue,这些容器都有不同的实现类,比如ArrayLIst、HashSet、HashMap、PriorityQueue等等,但是大部分都是非线程安全的,意味着在多线程访问...

    Java多线程之同步容器
  • Java多线程之ThreadLocal

    ThreadLocal的作用ThreadLocal的作用是提供线程内的局部变量,这个变量在同一个线程的生命周期内起作用,可以减少同一个线程内多个方法之前传入公共资源的复杂性,并且隔离其他线程。下面是一个使用ThreadLocal的例子...

    Java多线程之ThreadLocal
  • Java多线程之Lock

    引入Lock的原因Java提供了一个关键字synchronized用来保证同步访问,那为什么还需要使用Lock?最根本的原因就是使用synchronized会造成线程的阻塞,资源同时只能被一个线程访问,程序效率低。比如,多个线程查询读...

    Java多线程之Lock
  • Java多线程之synchronized

    多线程引发的安全问题由于线程是共享进程中的所有资源的,那么每个线程都可以去操作进程中的某一个资源,当多个线程操作同一个资源的时候就可能出现线程安全问题。比如两个线程对同一个实例变量做加1的操作,然后打印该变量,如果变量的初始值为0,当...

    Java多线程之synchronized
  • Java中的线程的创建

    Java创建线程的三种方式 继承Thread 实现Runnable 实现Callable 继承Thread创建线程通过继承Thread的方式,可以很快的创建一个线程,Thread中有一个run()方法,只需要重写该方法,将需要另外开...

    Java中的线程的创建
  • 线程和进程

    什么是进程在百度百科中,进程有两种定义,一种是狭义定义:进程是正在运行的程序实例,比如微信、Tomcat、MySQL,这些就是一个个进程。另一种就是广义的定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,它是操作...

    线程和进程
Please check the parameter of comment in config.yml of hexo-theme-Annie!