一、引言

        Redis是基于内存的缓存数据库,读写操作均基于内存进行。内存具有易失性,一但服务关闭则会导致数据丢失,解决办法便是对数据进行持久化。redis的数据持久化主要依靠AOF日志和RDB快照来实现,本文主要对AOF日志方式进行原理讲解。

二、AOF日志持久化机制讲解

        (一)持久化实现原理

        AOF日志用于存放redis执行过的命令,与mysql的binlog类似,只记录写操作。当redis服务关闭后再重启时,若有启动redis的AOF日志持久化(默认不开启),则会进行读取AOF日志的命令进行操作,实现数据的复原。

        (二)AOF日志写入策略

AOF写入包含三种策略,可在redis.*.conf中进行参数修改。

        Always(总是):每次执行命令就进行一次写入AOF文件。这种策略可靠性高,不易丢失大量数据,但对由于写入操作在redis的主线程执行,因此对redis的服务性能影响很大,可能导致redis操作阻塞。(单机下不推荐使用)

        Everysec(每秒):每秒进行一次命令写入AOF文件。这种策略可靠性取决于服务的写操作频繁程度。当服务器宕机时,最多丢失一秒的操作数据redis默认采用该种方式

yii2 redis操作日志 redis日志详解_数据库

        No: 当redis接收到用户端发来的写操作命令时,redis主线程会先对命令进行执行,执行完后再将redis命令写入到AOF缓冲区中,再由系统调用write()函数写入到AOF文件内核缓冲区中,由操作系统决定何时进行写入。该种策略性能最好,但服务器宕机后可能丢失的数据最多,数据安全性较差。

yii2 redis操作日志 redis日志详解_数据_02

        总结:三种策略并没有哪个就是最好或者最差,需要根据具体应用场景来进行AOF写入策略的选择。

三、AOF重写机制

        (一)引言

        在redis的长期使用下,我们不断的往AOF日志文件中写入命令,而一个redis的AOF日志文件又只有一个的情况下,会使得AOF日志文件过大,之后再对AOF读取以恢复数据将会变得更加耗时。为了解决这一问题,我们引入AOF重写机制。

        (二)AOF重写机制实现原理

        AOF重写机制:当AOF文件大小达到我们预先设置的文件阈值后,便会触发重写机制。该机制会新建一个临时AOF文件并读取当前redis数据库中的数据进行生成数据新增命令,随后将其写入到该临时AOF文件中,再用该AOF文件替代原来的文件以此实现AOF文件的压缩。

        与AOF写入的区别:AOF重写会新建一个子进程进行AOF文件操作不会影响redis服务性能,而AOF写入在redis的主进程中执行,会影响redis的服务性能。

        (三)重写时存在的问题

问题描述:

       我们在进行AOF重写时,往往redis的服务仍在正常进行,因此AOF重写进程读取到的数据可能为旧数据,在重写期间进行的命令便不会被记录,导致数据不一致问题。针对这个问题,我们应该如何进行解决呢?

解决方案:

        redis在AOF重写时,会新增一个重写缓冲区,在重写期间的写操作会额外写入到AOF重写缓冲区中,当重写结束后,将重写缓冲区里的写命令写入到新AOF文件中,写入完成后,AOF文件持久化正常进行,仍继续从AOF写入缓冲区中读取数据。

yii2 redis操作日志 redis日志详解_redis_03

或许有人会问为什么需要新增缓冲区而不直接使用原来的AOF缓冲区?

        我的理解是,在AOF进行重写操作时,AOF缓冲区会根据AOF写入策略往旧AOF文件中写入数据,而这些写入的操作会从缓冲区中被清除,这就导致了部分写入数据丢失,显然无法保证数据的一致性。而新增的重写缓冲区数据由于没有被读取过会继续存留直到被新的AOF读取。

PS:

        写这篇博客的目的主要是为了巩固我背的八股,在写这篇博客的时候,我对redis的AOF持久化有了更深的了解,博客的内容是结合小林coding和我个人的一些理解写下的。

        这是我第二次写博客,文字可能偏多了、表达和排版可能也存在问题,还希望大家可以留下自己的意见。由于文章包含个人理解,因此不能保证内容完全正确,如内容有误还望指正,我们共同成长。