美文网首页
MS-Redis-持久化

MS-Redis-持久化

作者: Captain_tu | 来源:发表于2019-01-11 14:37 被阅读10次

    Redis的数据是保存在内存中的,所以能保证很快的读写速度。但是如果发生不可抗的如断电,系统崩溃等因素,redis中的数据就会丢失。Redis支持将内存中的数据保存到硬盘来减少内存数据丢失带来的损失。这就是Redis的持久化

    Redis有两种持久化的方式,一种是通过屏幕快照(Snapshotting),一种是AOF(Append-Only-File)。

    1. RDB
      RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot),将内存中的数据以快照的数据写入到二进制文件(默认是dump.rdb,可在配置文件中修改,或者通过config set dir设置路径,通过config set dbfilename设置文件名称)中。

      • 快照规则
        快照的规则可以配置为,在n秒内如果超过m个key被修改,就自动快照,下边是配置文件中默认的规则:

        save 900 1 #900 秒内如果超过 1 个 key 被修改,则发起快照保存
        save 300 10 #300 秒内容如超过 10 个 key 被修改,则发起快照保存
        save 60 10000 #60 秒内容如超过 10000 个 key 被修改,则发起快照保存

      • 快照过程

        1. redis调用fork,创建子进程(子进程继承了父进程的整个地址空间,包括进程上下文,堆栈地址,内存信息进程控制块)。
        2. 父进程继续处理请求,子进程负责将内存内容写到临时文件。
          由于os的实时复制机制(copy on write),父子进程享有相同的物理页面,父进程处理写请求时,os会为其要修改的页面创建副本,而不是共享的页面。所以子进程地址空间内的数据是fork时整个数据库的一个快照。
        3. 子进程写入完毕后,用临时文件替换原来的快照文件,然后子进程退出
      • 手动写入快照
        可以通过save或者bgsave命令,通知redis做一次快照持久化。
        save操作是在主线程中保存快照的,而redis是单线程的,因此save操作会阻塞redis处理其他请求,因此不建议使用。

      • 数据丢失
        注意: 每次快照持久化都是将内存完整数据写入磁盘一次,而不是增量的同步变更数据,因此数据量大的时候,必然引起大的磁盘IO,可能会严重影响性能。

    2. AOF
      由于快照的方式是隔一段时间做一次的,因此如果redis意外down掉的话,就会丢失最后一次快照之后的所有修改。
      如果应用不允许丢失任何修改的话,就可以采用AOF的方式。

      • 过程原理
        使用AOF持久化时,Redis会把所有的写请求都通过write函数追加到文件中(默认是appendonly.aof),Redis重启时,通过执行文件中的写命令,将数据重新加载到内存中。

      • 数据丢失
        由于os会在内核中,缓存write做的修改,所以可能不会立即将写命令写入到磁盘文件中,从而可能会丢失部分修改。
        但是我们可以通过配置appendfsync,强制告诉os写入磁盘的时机。有以下三种方式:

        appendfsync always # 每一次的写操作都写入到磁盘,最慢,但是能保证完全的持久化
        appendfsync everysec # 每秒钟写入磁盘一次,在性能和持久化方面做了折中
        appendfsync no # 完全以来os的写入时机,性能最好,但持久化没保证
        
      • 问题
        持久化文件会越来越大。
        假如我们调用incr test100次,持久化文件中就会保存了100条incr命令,但是其中99条都是多余的,因为要恢复这个状态,我们只需要执行一次set test 100就可以了。

        使用bgrewriteaof命令,可以压缩aof持久化文件。这个命令的过程,类似于RDB方式写入快照的方式,会将内存中的数据以命令的方式写入临时文件,然后替换原来的持久化文件。具体过程如下:

        1. Redis fork出子进程。
        2. 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令。(这个命令不是client的写命令)
        3. 父进程继续处理client请求,除了把新的写请求写入到原来的aof文件中外,还把这些命令缓存起来。保证如果子进程重写失败后,原来的aof文件还能用。
        4. 子进程把快照写入到临时文件完成后,通知主进程把缓存的命令也写入到临时文件。
        5. 主进程用临时文件替换原来的aof文件,并重命名,后面收到的写命令也追加到新的aof文件中。

        :::: bgrewriteaof并没用读取旧的aof文件,而是将内存中的数据库内容用命令的方式重写了一份

    相关文章

      网友评论

          本文标题:MS-Redis-持久化

          本文链接:https://www.haomeiwen.com/subject/hxotdqtx.html