Redis的AOF机制

1、什么是AOF日志

    Redis是通过一条条命令行将数据存到内存中的,当Redis服务器意外宕机时,内存中的数据就会丢失,这个时候就需要使用AOF机制来恢复Redis的数据了。AOF机制就是将Redis执行的命令行记录成日志文件,然后存入到磁盘中。当出现意外后,将日志文件拿出来,然后再重新执行一遍,来防止数据的丢失。

2、如何实现AOF日志

    说到日志,我们可能会想到数据库的写前日志,即在数据写入之前,将这些修改数据的记录存到日志文件中,然而Redis的AOF日志正好相反,他是在Redis数据存入内存后再讲这些操作命令记录到数据库中的。如下图所示:

        

     这样做一方面是因为,这些操作命令成功存入到Redis中后,就表明这些语句是正确的,那存入日志文件的时候就不需要再对这些操作命令进行校验了。既保证了存储到日志文件的命令行时正确的,而且也加快了存储的效率。另一方面,在执行命令行后再记录日志也是为了不阻塞主线程的执行。因为记录日志和存储数据都是采用的主线程。

    不过AOF也存在两个问题:1、在存储数据后,记录日志的服务器宕机了。这样就会导致这次存储的数据丢失; 2、记录日志和存储数据都是采用的主线程,那当记录日志时,就不可避免的会导致主线程的阻塞,影响Redis的性能。

    为了解决这两个问题,Redis设计了三种写回策略:

    Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;

    Everysec,每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;

    No,操作系统控制的写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。

这3种策略各有优劣,如下图总结:

        

   其实这3中策略其实都没有完美的解决上面的两个问题,世上本就没有十全十美的事情。他们只是在性能和可靠性上做了平衡和取舍。当你需要高可靠时就使用Always,需要高性能时就使用NO,趋中时就使用Everysec。

    3、AOF重写机制

    当Redis运行越久,记录的日志文件就会越大,那么记录日志的时间就会越长,对主线程的阻塞就会越来越严重。这个时候就需要用到AOF重写机制了。

    AOF 重写机制就是在重写时,Redis 根据数据库的现状创建一个新的 AOF 文件,也就是说,读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写入。比如说,当读取了键值对“testkey”: “testvalue”之后,重写机制会记录 set testkey testvalue 这条命令。这样,当需要恢复时,可以重新执行该命令,实现“testkey”: “testvalue”的写入。

    为什么重写机制可以把日志文件变小呢? 实际上,重写机制具有“多变一”功能。所谓的“多变一”,也就是说,旧日志文件中的多条命令,在重写后的新日志中变成了一条命令。我们知道,AOF 文件是以追加的方式,逐一记录接收到的写命令的。当一个键值对被多条写命令反复修改时,AOF 文件会记录相应的多条命令。但是,在重写的时候,是根据这个键值对当前的最新状态,为它生成对应的写入命令。这样一来,一个键值对在重写日志中只用一条命令就行了,而且,在日志恢复时,只用执行这条命令,就可以直接完成这个键值对的写入了。

   

    如上图所示,当我们对一个列表先后做了 6 次修改操作后,列表的最后状态是[“D”, “C”, “N”],此时,只用 LPUSH u:list “N”, “C”, "D"这一条命令就能实现该数据的恢复,这就节省了五条命令的空间。对于被修改过成百上千次的键值对来说,重写能节省的空间当然就更大了。

猜你喜欢

转载自blog.csdn.net/q5926167/article/details/119039335