zoukankan      html  css  js  c++  java
  • Redis持久化

     一、Redis概述

      Redis(Remote Dictionary Server):远程字典服务器,是一个可基于内存亦可持久化的日志型、key-value数据库,Redis支持两种持久化方式RDB和AOF.

     二、RDB

      2.1、什么是RDB

        RDB:Redis DataBase,在指定的时间间隔内将内存中的数据集快照写入到磁盘中,也就是所谓的snapshot,它恢复时是将快照直接读入内存中.

      2.2、RDB实现原理

        Redis会单独创建(fork)一个子进程来进行持久化,它会将数据写入到一个临时文件中,待持久化过程完成后,再用这个临时文件替换掉上次持久化好的文件,整个过程中主进程是不会进行任何的IO操作的,这样就确保了极高的性能,如果需要进行大规模的数据恢复,并且对数据的完整性不是非常敏感,那么使用RDB方式就要比AOF方式更加的高效,RDB的缺点是最后一次的持久化数据有可能会丢失(最后一次数据未触发RDB持久化策略,也没有手动持久化,然后宕机了,这样最后一次的持久化数据就丢失了).

      2.3、fork原理

        fork就是复制出一个全新的进程,新进程所有的数据和原进程一模一样,并且是原进程的一个子进程.

      2.4、如何触发RDB持久化

      1、自动触发

    ################################ SNAPSHOTTING  ################################
    #
    # Save the DB on disk:
    #
    #   save <seconds> <changes>
    #
    #   Will save the DB if both the given number of seconds and the given
    #   number of write operations against the DB occurred.
    #
    #   In the example below the behaviour will be to save:
    #   after 900 sec (15 min) if at least 1 key changed
    #   after 300 sec (5 min) if at least 10 keys changed
    #   after 60 sec if at least 10000 keys changed
    #
    #   Note: you can disable saving completely by commenting out all "save" lines.
    #
    #   It is also possible to remove all the previously configured save
    #   points by adding a save directive with a single empty string argument
    #   like in the following example:
    #
    #   save "" // 如果你只是想使用Redis的缓存功能,不需要使用持久化,那么你可以注释掉所有的save行,然后只打开 save ""这一行配置,这就代表禁用RDB持久化功能
    
    save 900 1     // 900s内有一个写操作,Redis就会触发RDB持久化,将内存中的数据持久化到磁盘上.
    save 300 10    // 300s内有10个写操作,Redis就会触发RDB持久化,将内存中的数据持久化到磁盘上.
    save 60 10000  // 60s内有10000个写操作,Redis就会触发RDB持久化,将内存中的数据持久化到磁盘上.

      2、手动触发  

        save:该命令会阻塞当前Redis服务器,执行命令期间Redis不能处理其它命令,直到RDB持久化过程完成为止.

        bgsave:为了解决save命令对于内存比较大的实例会造成长时间的阻塞,Redis提供了bgsave命令,执行该命令时,Redis会在后台异步进行快照操作,快照操作的同时还能响应客户端的请求,具体的操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,阻塞只发生在fork阶段,一般持续很短的时间.

        flushall:使用该命令也会手动触发RDB持久化,对应的dump.rdb是空的.

    -rw-r--r--. 1 root root 92 7月  30 00:24 redis-6379-dump.rdb       //dump.rdb的大小为92,代表dump.rdb是一个空文件

        shutdown:客户端执行shutdown关闭Redis后台服务

       2.5、RDB常用配置详解

    #RDB核心规则配置 save <指定时间间隔> <执行指定次数更新操作>,满足条件就将内存中的数据同步到硬盘中.
    官方出厂配置默认是: 
    900秒内有1个更改
    300秒内有10个更改
    60秒内有10000个更改
    如果满足上面设置的触发条件,则将内存中的数据快照写入磁盘.
    若不想用RDB方案,可以把 save "" 的注释打开,代表禁用RDB持久化方案.
    # save ""
    save 900 1      // 900s内如果有一个更改则触发RDB保存,文件名为xxx.dump
    save 300 10     //  300s内如果有10个更改,则触发保存
    save 60 10000    //  60s内如果有10000个更改则触发保存
    
    #当RDB持久化出现错误后,是否依然继续进行工作
    yes:不能进行工作
    no:可以继续进行工作
    可以通过info中的rdb_last_bgsave_status了解RDB持久化是否有错误
    stop-writes-on-bgsave-error yes
     
    #配置存储至本地数据库时是否压缩数据,默认为yes。
    Redis采用LZF压缩方式,但占用了一点CPU的时间.若关闭该选项,但会导致数据库文件变的非常巨大.建议开启.
    rdbcompression yes
     
    #是否校验rdb文件,从rdb格式的第五个版本开始,在rdb文件的末尾会带上CRC64的校验和.
    这样做有利于文件的容错性,但是在保存rdb文件的时候,会有大概10%的性能损耗.
    所以如果你追求高性能,可以关闭该配置.
    rdbchecksum yes
     
    #指定本地数据库文件名,一般采用默认的dump.rdb
    dbfilename dump.rdb
     
    #数据目录,数据库的写入会在这个目录.rdb、aof文件也会写在这个目录.
    例如 dir配置为./  dbfilename配置为dump.rdb,那么你的持久化数据保存在 ./dump.rdb路径下
    例如 dir配置为/opt/myredis/var  dbfilename配置为dump6379.rdb那么redis使用rdb持久化的数据保存在
    /opt/myredis/var/dump6379.rdb路径下.
    dir ./
      
    

    三、AOF  

      3.1、什么是AOF

        AOF:Append Only File,以日志的形式记录每一个写操作,将Redis执行过的所有写指令记录下来(读指令不记录),只允许追加文件但是不能改写文件,Redis启动之初会读取该文件然后重新构建数据,换言之,Redis重启就是根据日志文件的内容将所有的写指令重新执行一次,以完成数据的恢复工作.

      3.2、如何开启AOF方式持久化Redis数据

        Redis默认情况下是不开启AOF持久化方式的,如果要开启AOF持久化方式需要在Redis配置文件中进行配置,将下面配置修改为yes(默认是no).

    appendonly yes
    

      3.3、同时开启RDB和AOF,那么Redis重新启动恢复数据的时候到底会采用哪种方式恢复数据呢.

        Redis默认情况下使不开启AOF持久化方式的,如果RDB和AOF同时开启的情况下,Redis恢复数据会优先采用AOF的方式恢复数据,这样丢失的数据会更少.

      3.4、AOF重写原理和机制

        1、为什么会重写

        AOF采用文件追加的方式,随着时间的推移,.aof文件会越来越大,为了避免这种情况,AOF方式增加了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteof来手动重写.

        2、重写原理

        AOF文件持续增长而过大时,会fork出一条新的进程来将文件重写(也是先写临时文件,然后再rename),遍历新进程内存中的数据,然后根据内存中的数据而创建出可以恢复数据的最小指令集,重写AOF文件操作的时候,并没有读取旧的AOF文件,而是将真个内存中的数据库内容用命令的方式重写了一个新的AOF文件.

        3、如何触发重写

        重写虽然可以节约大量的磁盘空间,恢复数据时也可以减少时间,但是每次重写还是有负担的,需要满足下列条件才能触发重写机制

    auto-aof-rewrite-percentage 100    
    auto-aof-rewrite-min-size 64mb
    
    系统载入时或者上次重写完毕时,Redis会记录此时AOF文件的大小,假设为base_size,
    如果当前RedisAOF文件
    大小>=base_size*(100+100)%
    大小>64mb
    同时满足这两个条件时便会触发重写机制

        4、AOF常用配置详解

    ################################# APPEND ONLY MODE #################################
    #Redis 默认不开启AOF.它的出现是为了弥补RDB的不足(未触发RDB持久化策略,然后宕机的情况下,最后一次未持久化的数据可能会丢失可能会丢失).
    所以它采用日志的形式来记录每个写操作,并追加到文件中.Redis重启的会根据日志文件的内容将写指令从前到后执行一次
    以完成数据的恢复工作,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了.但是redis如果中途宕机,
    会导致可能有几分钟的数据丢失,根据save策略来进行持久化.
    Append Only File是另一种持久化方式,可以提供更好的持久化特性.Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件
    每次启动时Redis都会先把这个文件的数据读入内存中,如果开启rdb则使用appendonly no,如果开启aof则使用 appendonly yes
    appendonly no
     
    #指定aof模式下本地数据库文件名,默认值为 appendonly.aof
    appendfilename "appendonly.aof"
     
    #aof持久化策略的配置:
    no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快
    everysec表示每秒执行一次fsync,可能会导致丢失这1s数据
    always表示每次写入都执行fsync,以保证数据同步到磁盘,速度最慢
    默认使用 everysec
    appendfsync always
    appendfsync everysec
    appendfsync no
     
    # 在aof重写或者写入rdb文件的时候,会执行大量IO,此时对于everysec和always的aof模式来说,执行
    fsync会造成阻塞过长时间,no-appendfsync-on-rewrite字段设置为默认设置为no.如果对延迟要求很高的
    应用,这个字段可以设置为yes,否则还是设置为no,这样对持久化特性来说这是更安全的选择.设置为yes表
    示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes.Linux的
    默认fsync策略是30秒。可能丢失30秒数据
    no-appendfsync-on-rewrite no
     
    #aof自动重写配置.当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,
    即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写.
    当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过.
    auto-aof-rewrite-percentage 100
     
    #设置允许重写的最小aof文件大小,避免了达到约定百分比但.aof文件尺寸仍然很小的情况还要重写
    auto-aof-rewrite-min-size 64mb
     
    #aof文件可能在尾部是不完整的,当redis启动的时候,aof文件的数据被载入内存.
    重启可能发生在redis所在的主机操作系统宕机后,尤其在ext4文件系统没有加上data=ordered选项
    (redis宕机或者异常终止不会造成尾部不完整现象.)出现这种现象,可以选择让redis退出,
    或者导入尽可能多的数据.如果选择的是yes,当截断的aof文件被导入的时候,
    会自动发布一个log给客户端然后load.如果是no,用户必须手动redis-check-aof修复AOF文件才可以
    aof-load-truncated yes
     
    #加载redis时,可以识别AOF文件以“redis”开头.字符串并加载带前缀的RDB文件,然后继续加载AOF尾巴
    aof-use-rdb-preamble yes
    

      

     4、RDB和AOF的区别以及选择

      RDB AOF
    区别 RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储. AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录.
    优点 这种文件非常适合用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。RDB 非常适用于灾难恢复(disaster recovery)。 使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的 fsync 策略,比如无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。 AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,所以主线程可以继续努力地处理命令请求)。
    缺点 如果你需要尽量避免在服务器故障时丢失数据,那么 RDB 不适合你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
    选择

    如果你非常关心你的数据,但仍然可以承受数分钟以内的数据丢失, 那么你可以选择使用 RDB 持久化.

    如果你非常关心你的数据的完整性,并且可以接受处理巨大的写入而导致Redis 的性能降低的负面影响,那么你可以选择使用AOF持久化.
  • 相关阅读:
    深入理解递归函数的调用过程
    关于字符串和字符数组的再讨论
    返回字符串的长度
    再写静态变量的有效范围
    一道关于返回指针和返回数组名的面试题
    关于TCP/IP的三次握手和四次挥手解释
    C++面向对象的编程(二)
    关于面试宝典中的检测并修改不适合的继承
    argc和argv
    基于C的文件操作(转)
  • 原文地址:https://www.cnblogs.com/xiaomaomao/p/13396767.html
Copyright © 2011-2022 走看看