V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shiziwen
V2EX  ›  Redis

在 Redis 中, AOF 缓冲区和 AOF 重写缓冲区的区别是什么?

  •  
  •   shiziwen · 2015-05-25 22:48:53 +08:00 · 6185 次点击
    这是一个创建于 3469 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请问在Redis中,AOF缓冲区和AOF重写缓冲区的区别是什么?
    设置AOF重写缓冲区,是为了在Redis在进行AOF重写期间引起的数据不一致问题,
    但是,所有的写命令都会写到AOF缓冲区和AOF重写缓冲区,这样的话,AOF缓冲区的内容应该是和AOF重写缓冲区的内容是一致的呀,AOF缓冲区也就可以替代AOF重写缓冲区了。

    是不是我哪里理解错了,多谢。

    8 条回复    2018-06-20 21:53:08 +08:00
    nekoyaki
        1
    nekoyaki  
       2015-05-26 10:04:19 +08:00
    aof实际上就是文本格式的追加指令,所以随着使用,会变得越来越大越来越大。比如我有一个API,会让某值自增1。如果我调用一万次这个API,那这个指令在aof里就会记录一万次。
    aof重写的作用是,把这个很大很大的aof文件给重写,变得小一点。那一万次自增,会变成一条直接加到一万零一的数据。
    那么,有几个问题。
    1、aof重写的时候,是不是不应该阻塞主线程?
    2、如果重写的时候被中断了,怎么办?

    所以AOF重写缓冲区的意义就在这儿了。另起一个缓冲区,在别的线程里重写AOF,便于在重写完成前保证原aof的安全。
    shiziwen
        2
    shiziwen  
    OP
       2015-05-26 10:35:05 +08:00
    @nekoyaki ,多谢。
    AOF重写缓冲区的作用,是为了避免数据不一致的发生,在重写完成后,会将AOF重写缓冲区的内容,同步到AOF缓冲区中。

    问题是,AOF重写的过程中,写操作是否也会追加到AOF缓冲区中。如果这样的话,AOF缓冲区和AOF重写缓冲区的内容,将会是一致的。
    看来得去看一下源码。
    fszaer
        3
    fszaer  
       2015-05-28 12:40:29 +08:00
    @shiziwen
    不对,并不是在重写完成后,将AOF重写缓冲区的内容,同步到AOF缓冲区中。
    实际上的过程应该是
    开始aof重写
    主程继续处理命令请求。
    将写命令追加到现有的 AOF 文件中。
    将写命令追加到 AOF 重写缓存中
    (这时aof缓存的内容由于已经写到aof文件和重写缓存中,不再需要保留,已经被释放了)。
    重写完成后将缓存写入到重写文件尾
    将文件改名覆盖原来的aof文件

    重写缓存主要是为了记录重写过程中的不同(主要是新增写/删等命令),并不会和缓存区保持一致,要保持一致的重写前的aof文件,aof重写文件还有数据库本身

    要了解redis设计与实现除了读官方源码以外,我无脑推荐《Redis 设计与实现 第二版》这本书,以及作者对源码的中文注释(对新手更友好)
    shiziwen
        4
    shiziwen  
    OP
       2015-05-28 15:21:19 +08:00
    @fszaer
    重写过程中,新建一个子进程进行重写。
    主进程继续处理客户端的命令请求,此时,写命令是追加到AOF缓存,还是追加到现有的AOF文件?
    重写的过程中,AOF缓存和AOF文件是一个什么状态?

    多谢。
    fszaer
        5
    fszaer  
       2015-05-28 20:02:34 +08:00
    @shiziwen
    啊,对不起 我也搞混了一点

    首先要说明的一点是,重写时并不影响aof持久化正常执行也不影响现有的aof缓存区跟aof文件。

    如果我们简化aof持久化的正常过程是新命令->缓存区->aof文件的顺序

    那么在执行重写时,而又有新命令的话
    就只是在新命令->缓存区
    这一过程的之间把命令复制一份到重写缓存区中
    事实上每次缓存区写入文件时都会检查是否在重写以判断需不需要写多一份到重写缓存区。
    所以我早上说的缓存区冲洗到aof文件之后再写到重写缓存区是错的

    但是两个缓存区依然是很难保持一致的
    虽然两个缓存区在新命令->缓存区这一步之后看上去是一致的(?),但是这是暂时的
    因为aof缓存区在写到aof文件中之后,会被清空或者直接指向一片新的内存空间,以便确保有足够的空间继续接受新的命令。显然,这之后两个缓存区就不再一致了。

    aof重写缓存区会一直保持从重写开始到结束所有写命令
    而aof缓存区会不断 写入-冲洗到aof文件-清除-写入 这一过程,因而只会保存一部分的命令
    他们并不一致

    假如只保留一个缓存区,就可能有以下麻烦
    没有办法很好分离两个功能互不影响
    标识重写过程中新增命令变得麻烦
    内存利用不够充分

    最后继续推荐《Redis 设计与实现 第二版》这本书,以及作者对源码的中文注释版
    fszaer
        6
    fszaer  
       2015-05-29 08:48:01 +08:00
    @fszaer
    勘误,
    事实上每次缓存区写入文件时都会检查是否在重写以判断需不需要写多一份到重写缓存区。
    这里应该是
    每次有新命令写入缓存区时时都会检查是否在重写,以判断需不需要写多一份到重写缓存区。
    最近脑子老是秀逗=、=
    ccqy66
        7
    ccqy66  
       2018-05-04 19:29:51 +08:00
    说一下个人的理解吧:
    AOF 缓冲区的作用:目的是维持主线程 AOF 文件的正常写入,保证在重写阶段,AOF 文件写入的逻辑不变。
    AOF 重写缓存区作用:目的是记录 AOF 重写开始之后的键增删改的命令。
    这两个缓冲区缺一不可。具体原因如下:
    AOF 缓冲区的内容会根据 appendfsync 策略的不同而不同,如果 appendfsync=always,那么每次命令都会立即被刷入到磁盘里,可能 AOF 缓存区就没有数据。而 AOF 重写缓存区一定是从重写开始之后所有的键增删改的命令。两个缓冲区从存在意义上来看是完全不一样的,前者侧重于功能,后者更加侧重于备份。
    XDMonkey
        8
    XDMonkey  
       2018-06-20 21:53:08 +08:00
    @ccqy66 实际上两个缓冲区就是对应重写前后的两个 AOF 文件吧 我的理解
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2815 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 13:30 · PVG 21:30 · LAX 05:30 · JFK 08:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.