Redis数据丢失怎么办?AOF日志

817 阅读4分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

大家都知道使用Redis速度很快,是因为Redis把数据都存储在内存中。一旦服务器宕机,内存中的数据将全部丢失。

即使重启后,也需要从后端数据库重新生成数据,然后放入内存中。但是短时间内从数据库中读取大量数据,数据库压力会比较大。另外从数据库读取数据的时间会比较长。服务器宕机后还有可能会丢失数据。

所以需要Redis也可以实现数据的持久化,避免上述情况。

Redis使用AOF日志和RDB快照的方式持久化数据,今天先看下AOF日志。

AOF日志如何实现

当AOF持久化功能打开后,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器的 aof_buf 缓冲区中。由于是在命令执行完之后才会把命令追加到文件中,所以不会阻塞当前命令的执行。

但是如果当前命令执行完之后,服务器宕机,由于还没有记录日志,则会导致数据丢失。

AOF虽然不会阻塞当前命令,但是可能会阻塞之后执行的命令。因为AOF日志也是在Redis主线程里面执行的,并且由于要把命令写入磁盘,导致执行速度比较慢。

AOF写入磁盘是个性能瓶颈,因此提供了三种写回策略。

AOF日志写回策略

AOF机制提供三种写回策略,也是配置项 appendfsync 的三个可选项。

AOF_FSYNC_NO :操作系统控制写回。每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。在这种模式下,Redis会在以下时机把AOF写入磁盘。

-   Redis 被关闭
-   AOF 功能被关闭
-   系统的写缓存被刷新(可能是缓存已经被写满,或者定期保存操作被执行)

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

AOF_FSYNC_ALWAYS :每执行一个命令执行一次。每个写命令执行完,立马同步地将日志写回磁盘。

每执行一个命令都写入磁盘可以保证数据基本不丢失,但是AOF日志写入磁盘会造成主线程阻塞。

每秒执行一次写盘保证了性能,但是可能会丢失一秒内写入的数据。

由操作系统控制写回性能最好,但是如果发生服务器宕机,丢失的数据也最多。

因此,基本排除由操作系统写回策略,如果想要性能,那就选择每秒写回策略;如果保证数据不丢失,那就选择每执行一个命令都写回磁盘策略。

AOF日志重写

由于AOF日志是使用文件存储。当文件特别大时,操作文件追加命令的效率会变低。另外如果服务器宕机,需要使用AOF日志恢复数据时,时间也会比较长。

这时候AOF日志重写就派上了用场。

AOF日志内保存的是每次执行的命令。如果对一条数据操作了100次,那么就会保存100次命令。但是如果需要恢复数据的话,我们需要的是数据最新的状态,不需要知道被修改的过程。把多条命令变成一条命令,便实现了AOF的重写。

重写时,主线程 fork 出后台的 bgrewriteaof 子进程执行。此时,fork 会把主线程的页表拷贝一份给 bgrewriteaof 子进程,如果Redis中数据量很大,主线程的页表也会很多,因此可能会阻塞主线程。但是执行重写的过程不会阻塞主线程。