Redis--基础知识点--18--aof能保证数据100%不丢失吗?

我们都知道 Redis 的数据全部在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证 Redis 的数据不会因为故障而丢失,这种机制就是 Redis 的持久化机制。

    众所周知,Redis 的持久化机制有两种,第一种是快照RDB,第二种是 AOF 日志。快照是一次全量备份,AOF 日志是连续的增量备份。快照是内存数据的二进制序列化形式,在存储上非常紧凑,基本一次五分钟左右,而 AOF 日志记录的是内存数据修改的指令记录文本。AOF 日志在长期的运行过程中会变得无比庞大,数据库重启时需要加载 AOF 日志进行指令重放,这个时间就会无比漫长,所以需要定期进行 AOF 重写,给 AOF 日志进行瘦身。

    那么,RDB或者AOF能否保证数据百分百不丢失?疑问的我在百度上搜了搜,发现很多博客都讲,将appendfsync值设置为always就可以了。这回答让我对《redis设计与实现》产生了怀疑。难道新版本的redis能够保证数据100%不丢失?!

我们来看一下aof 设置always的源码分析

void flushAppendOnlyFile(int force) {    
    if (sdslen(server.aof_buf) == 0) return;
    if (server.aof_fsync == AOF_FSYNC_EVERYSEC)
        sync_in_progress = bioPendingJobsOfType(BIO_AOF_FSYNC) != 0;
    if (server.aof_fsync == AOF_FSYNC_EVERYSEC && !force) {
        if (sync_in_progress) {
            if (server.aof_flush_postponed_start == 0) {
                server.aof_flush_postponed_start = server.unixtime;
                return;
            } else if (server.unixtime - server.aof_flush_postponed_start < 2) {
                return;
            }
            server.aof_delayed_fsync++;
        }
    }
    //将aof_buf中的内容写入到aof文件
    nwritten = write(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));
    server.aof_flush_postponed_start = 0;
    ……
    server.aof_current_size += nwritten;
    if ((sdslen(server.aof_buf)+sdsavail(server.aof_buf)) < 4000) {
        sdsclear(server.aof_buf);
    } else {
        sdsfree(server.aof_buf);
        server.aof_buf = sdsempty();
    }
    //appendfsync为no或者有后台进程在进行aof或rdb,不进行文件同步
    if (server.aof_no_fsync_on_rewrite &&
        (server.aof_child_pid != -1 || server.rdb_child_pid != -1))
            return;
    /* appendfsync为always */
    if (server.aof_fsync == AOF_FSYNC_ALWAYS) {/
        aof_fsync(server.aof_fd); //同步aof文件
        server.aof_last_fsync = server.unixtime;//记录同步时间
    } else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC &&
                server.unixtime > server.aof_last_fsync)) {
        /* appendfsync为EVERYSEC*/
        if (!sync_in_progress) aof_background_fsync(server.aof_fd);
        server.aof_last_fsync = server.unixtime;
    }
}
void aof_background_fsync(int fd) {
    bioCreateBackgroundJob(BIO_AOF_FSYNC,(void*)(long)fd,NULL,NULL);
}

可以看到,在方法中,有if (server.aof_fsync == AOF_FSYNC_ALWAYS)的判断,如果条件符合,会使用fdatasync()的方法来写磁盘。

大体就是:先把写命令追加到aof buffer中,下一次进入事件循环循环后,再将buffer写到磁盘上。结合while循环处方法的调用顺序,可以看出确实是这样的。那么也就是说,这次写到磁盘上的内容是上一个事件循环产生的

所以,即使设置为always,也会丢失一个循环的数据。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值