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

    1.Redis持久化

      RDB(Redis DataBase)

        AOF(Append Only File)

    2.RBD

      1)基本说明

        在指定的时间间隔内将内存中的数据集快照写入磁盘文件,它恢复时将快照文件直接读到内存里。

            Redis会单独创建(Fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失(上一次持久化后写入的数据在内存中,还没有持久化。系统挂了的话,这些数据就没有了)。也就是说它是每次生成一个完整数据的新的文件替换上次的。

         Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量‘程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。子进程所占用的内存比会和父进程一模一样,它们有相同的数据。如会造成CPU负担。

           RDB保存的是dump.rdb文件---这个文件最好要备份到其它机械以保障数据的安全

      2.RBD的持久化策略

        默认的配置:

        #在900秒之内有1个keys发生变化时触发持久化
        #30秒之内有10个keys发生变化时触发持久化
        #60秒之内有10000个keys发生变化时触发持久化
        save 900 1
        save 300 10
        save 60 10000

        也就是说RDB持久化是按时间切片进行的。

      3.RDB相关配置

       1.save
        #设置RDB进行数据库镜像持久化的频率。 保存数据到disk的策略
        #900秒之内有1个keys发生变化时
        #30秒之内有10个keys发生变化时
        #60秒之内有10000个keys发生变化时
        save 900 1
        save 300 10
        save 60 10000

        2.rdbcompression
        #在进行RDB镜像备份时,是否进行压缩
        rdbcompression yes

        3.dbfilename
        #镜像备份文件的文件名-RDB持久化数据保存的文件名称
        dbfilename dump.rdb

           4.dir
        #数据库镜像备份的文件放置的路径-RDB持久化数据保存的文件路径
        #路径跟文件名分开配置是因为 Redis 备份时,先会将当前数据库的状态写入到一个临时文件
        #等备份完成时,再把该临时文件替换为上面所指定的文件
        #而临时文件和上面所配置的备份文件都会放在这个指定的路径当中
        #默认值为 ./  redis启动目录
        dir /var/lib/redis/

       5.rdbchecksum yes

        是否进行校验和,是否对rdb文件使用CRC64校验和,默认为"yes",那么每个rdb文件内容的末尾都会追加CRC校验和,利于第三方校验工具检测文件完整性,读取和写入时候,会损失10%性能

       6.stop-writes-on-bgsave-error yes
        当持久化出现错误时,是否依然继续进行工作,是否终止所有的客户端write请求。默认设置"yes"表示终止,一旦snapshot数据保存故障,那么此server为只读服务。如果为"no",那么此次snapshot将失败,但下一次snapshot不会受到影响,不过如果出现故障,数据只能恢复到"最近一个成功点"

      4.save和bsave命令

       Save  在redis运行中,我们可以显示的发送一条save命令来拍摄快照。save命令是阻塞命令,也就是当服务器接收了一条save命令之后就会开始拍摄快照,在此期间不会再去处理其他的请求,其他请求会被挂起直到备份结束。

        bgsave命令也是立即拍摄快照,有别于save命令,bgsave并不是一条阻塞命令,而是fork一个子线程,然后这个子线程负责备份操作。而父进程继续处理客户端的请求,这样就不会造成阻塞了。可以通过lastsave命令获取最后一次成功执行快照的时间。

      5.内存数据没了后如何恢复数据到内存

        启动redis,就会自动恢复了

      6.怎么停止

        动态所有停止RDB保存规则的方法:redis-cli config set save ""

      7.优点

        适合大规模的数据恢复

          适合对数据完整性和一致性要求不高

      8.缺点

        在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。

          Fork的时候,内存中的数据被克隆了一份,大约2倍的膨胀性需要考虑。子进程所占用的内存比会和父进程一模一样,如会造成CPU负担。

      9.小结
        RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所有RDB持久化方式可以最大化redis的性能。
        与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些。
        数据丢失风险大,RDB需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能导致Redis在一些毫秒级不能响应客户端请求。

    3.AOF

      1.基本说明

         以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

        2.持久化策略
        appendfsync配置

        #always 表示每次有写操作都进行同步,everysec 表示每秒同步一次。
        #no表示等操作系统进行数据缓存同步到磁盘, 进行同步

        #everysec 表示每秒同步一次
        # appendfsync always :
        appendfsync everysec
        # appendfsync no

      3.相关配置

      1.appendonly
        #redis  默认每次更新操作后会在后台异步的把数据库镜像备份到磁盘,但该备份非常耗时,且备份不宜太频繁
        #redis 同步数据文件是按上面save条件来同步的
        #如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失
        #所以redis提供了另外一种更加高效的数据库备份及灾难恢复方式
        #开启append only 模式后,redis 将每一次写操作请求(记录的是写操作命令)都追加到appendonly.aof 文件中
        #redis重新启动时,会从该文件恢复出之前的状态。
        #但可能会造成 appendonly.aof 文件过大,所以redis支持BGREWRITEAOF指令,对appendonly.aof重新整理

        #简单来说就是开启AOF,默认是no
        appendonly no

      2.appendfilename
        # appendfilename appendonly.aof

      3.appendfsync
        #设置对 appendonly.aof 文件进行同步的频率-AOF持久化策略
        #always 表示每次有写操作都进行同步,everysec 表示对写操作进行累积,每秒同步一次。
        #no表示等操作系统进行数据缓存同步到磁盘, 都进行同步

        #everysec 表示每秒同步一次
        # appendfsync always :
        appendfsync everysec
        # appendfsync no

      4.no-appendfsync-on-rewrite no
        在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。默认为no,表示"不暂缓",新的aof记录仍然会被立即同步
      5.auto-aof-rewrite-percentage 100
        当Aof log增长超过指定比例时,重写log file, 设置为0表示不自动重写Aof 日志,重写是为了使aof体积保持最小,而确保保存最完整的数据。
      6 auto-aof-rewrite-min-size 64mb
        触发aof rewrite的最小文件尺寸

     4.怎么恢复数据

        启动redis自动恢复。AOF启动/修复/恢复(RDB和AOF同时存在时,先加载AOF来恢复的)

     5.AOF文件异常

        异常恢复(AOF文件写道一半系统崩掉了,AOF文件里面内容就存在问题)。Redis-check-aof --fix AOF文件名  进行修复,它会把不符合语法条件的语句删除掉

     6.重写

      AOF采用文件追加方式,也就是在之前的文件上继续写(RBD是替换上次的文件),文件会越来越大,为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集(一条数据一个set语句)。可以使用命令gbrewriteaof。

      AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后在rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

      Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。

      AOF的重写是由Redis主线程之外一个子线程执行,是在AOF写入的时候,会重新建立一个AOF重写缓冲区,当用户对数据库进行操作时,会把用户的操作追加到AOF重写缓冲区和AOF缓冲区中,此时AOF文件写入操作会同时从AOF缓冲区和AOF重写缓冲区两个地方读入数据,这样就保证了用户的添加修改操作的不丢失

     7.优点

      数据比较完善。

     8.缺点

      相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb 

      AOF运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同

    AOF持久化原理  https://zhuanlan.zhihu.com/p/75894903

    Redis 是一种内存数据库,将数据保存在内存中,读写效率要比传统的将数据保存在磁盘上的数据库要快很多。但是一旦进程退出,Redis 的数据就会丢失。

    AOF( append only file )持久化以独立日志的方式记录每次写命令,并在 Redis 重启时在重新执行 AOF 文件中的命令以达到恢复数据的目的。AOF 的主要作用是解决数据持久化的实时性。

    RDB 和 AOF

    antirez 在《Redis 持久化解密》一文中讲述了 RDB 和 AOF 各自的优缺点:

    • RDB 是一个紧凑压缩的二进制文件,代表 Redis 在某个时间点上的数据备份。非常适合备份,全量复制等场景。比如每6小时执行 bgsave 备份,并把 RDB 文件拷贝到远程机器或者文件系统中,用于灾难恢复。
    • Redis 加载 RDB 恢复数据远远快于 AOF 的方式
    • RDB 方式数据没办法做到实时持久化,而 AOF 方式可以做到。

    下面,我们就来了解一下 AOF 是如何做到实时持久化的。

    AOF 持久化的实现

     

    如上图所示,AOF 持久化功能的实现可以分为命令追加( append )、文件写入( write )、文件同步( sync )、文件重写(rewrite)和重启加载(load)。其流程如下:

    • 所有的写命令会追加到 AOF 缓冲中。
    • AOF 缓冲区根据对应的策略向硬盘进行同步操作。
    • 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
    • 当 Redis 重启时,可以加载 AOF 文件进行数据恢复。

    命令追加

    当 AOF 持久化功能处于打开状态时,Redis 在执行完一个写命令之后,会以协议格式(也就是RESP,即 Redis 客户端和服务器交互的通信协议 )将被执行的写命令追加到 Redis 服务端维护的 AOF 缓冲区末尾。

    比如说 SET mykey myvalue 这条命令就以如下格式记录到 AOF 缓冲中。

    "*3
    $3
    SET
    $5
    mykey
    $7
    myvalue
    "

    Redis 协议格式本文不再赘述,AOF之所以直接采用文本协议格式,是因为所有写入命令都要进行追加操作,直接采用协议格式,避免了二次处理开销。

    文件写入和同步

    Redis 每次结束一个事件循环之前,它都会调用 flushAppendOnlyFile 函数,判断是否需要将 AOF 缓存区中的内容写入和同步到 AOF 文件中。

    flushAppendOnlyFile 函数的行为由 redis.conf 配置中的 appendfsync 选项的值来决定。该选项有三个可选值,分别是 alwayseverysecno

    • always:Redis 在每个事件循环都要将 AOF 缓冲区中的所有内容写入到 AOF 文件,并且同步 AOF 文件,所以 always 的效率是 appendfsync 选项三个值当中最差的一个,但从安全性来说,也是最安全的。当发生故障停机时,AOF 持久化也只会丢失一个事件循环中所产生的命令数据。
    • everysec:Redis 在每个事件循环都要将 AOF 缓冲区中的所有内容写入到 AOF 文件中,并且每隔一秒就要在子线程中对 AOF 文件进行一次同步。从效率上看,该模式足够快。当发生故障停机时,只会丢失一秒钟的命令数据。
    • no:Redis 在每一个事件循环都要将 AOF 缓冲区中的所有内容写入到 AOF 文件。而 AOF 文件的同步由操作系统控制。这种模式下速度最快,但是同步的时间间隔较长,出现故障时可能会丢失较多数据。

    Linux 系统下 write 操作会触发延迟写( delayed write )机制。Linux 在内核提供页缓存区用来提供硬盘 IO 性能。 write 操作在写入系统缓冲区之后直接返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区页空间写满或者达到特定时间周期。同步文件之前,如果此时系统故障宕机,缓冲区内数据将丢失。

    fsync 针对单个文件操作,对其进行强制硬盘同步, fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。

    appendfsync的三个值代表着三种不同的调用 fsync的策略。调用 fsync周期越频繁,读写效率就越差,但是相应的安全性越高,发生宕机时丢失的数据越少。

    AOF 数据恢复

    AOF 文件里边包含了重建 Redis 数据所需的所有写命令,所以 Redis 只要读入并重新执行一遍 AOF 文件里边保存的写命令,就可以还原 Redis 关闭之前的状态。

    Redis 读取 AOF 文件并且还原数据库状态的详细步骤如下:

    • 创建一个不带网络连接的的伪客户端( fake client),因为 Redis 的命令只能在客户端上下文中执行,而载入 AOF 文件时所使用的的命令直接来源于 AOF 文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行 AOF 文件保存的写命令,伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样的。
    • 从 AOF 文件中分析并取出一条写命令。
    • 使用伪客户端执行被读出的写命令。
    • 一直执行步骤 2 和步骤3,直到 AOF 文件中的所有写命令都被处理完毕为止。

    当完成以上步骤之后,AOF 文件所保存的数据库状态就会被完整还原出来。

    AOF 重写

    因为 AOF 持久化是通过保存被执行的写命令来记录 Redis 状态的,所以随着 Redis 长时间运行,AOF 文件中的内容会越来越多,文件的体积也会越来越大,如果不加以控制的话,体积过大的 AOF 文件很可能对 Redis 甚至宿主计算机造成影响。

    为了解决 AOF 文件体积膨胀的问题,Redis 提供了 AOF 文件重写( rewrite) 功能。通过该功能,Redis 可以创建一个新的 AOF 文件来替代现有的 AOF 文件。新旧两个 AOF 文件所保存的 Redis 状态相同,但是新的 AOF 文件不会包含任何浪费空间的荣誉命令,所以新 AOF 文件的体积通常比旧 AOF 文件的体积要小得很多。

    如上图所示,重写前要记录名为 list的键的状态,AOF 文件要保存五条命令,而重写后,则只需要保存一条命令。

    AOF 文件重写并不需要对现有的 AOF 文件进行任何读取、分析或者写入操作,而是通过读取服务器当前的数据库状态来实现的。首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令,这就是 AOF 重写功能的实现原理。

    在实际过程中,为了避免在执行命令时造成客户端输入缓冲区溢出,AOF 重写在处理列表、哈希表、集合和有序集合这四种可能会带有多个元素的键时,会先检查键所包含的元素数量,如果数量超过 REDISAOFREWRITEITEMSPER_CMD ( 一般为64 )常量,则使用多条命令记录该键的值,而不是一条命令。

    rewrite的触发机制主要有一下三个:

    • 手动调用 bgrewriteaof 命令,如果当前有正在运行的 rewrite 子进程,则本次rewrite 会推迟执行,否则,直接触发一次 rewrite。
    • 通过配置指令手动开启 AOF 功能,如果没有 RDB 子进程的情况下,会触发一次 rewrite,将当前数据库中的数据写入 rewrite 文件。
    • 在 Redis 定时器中,如果有需要退出执行的 rewrite 并且没有正在运行的 RDB 或者 rewrite 子进程时,触发一次或者 AOF 文件大小已经到达配置的 rewrite 条件也会自动触发一次。

    AOF 后台重写

    AOF 重写函数会进行大量的写入操作,调用该函数的线程将被长时间阻塞,所以 Redis 在子进程中执行 AOF 重写操作。

    • 子进程进行 AOF 重写期间,Redis 进程可以继续处理客户端命令请求。
    • 子进程带有父进程的内存数据拷贝副本,在不适用锁的情况下,也可以保证数据的安全性。

    但是,在子进程进行 AOF 重启期间,Redis接收客户端命令,会对现有数据库状态进行修改,从而导致数据当前状态和 重写后的 AOF 文件所保存的数据库状态不一致。

    为此,Redis 设置了一个 AOF 重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当 Redis 执行完一个写命令之后,它会同时将这个写命令发送给 AOF 缓冲区和 AOF 重写缓冲区。

    当子进程完成 AOF 重写工作之后,它会向父进程发送一个信号,父进程在接收到该信号之后,会调用一个信号处理函数,并执行以下工作:

    • 将 AOF 重写缓冲区中的所有内容写入到新的 AOF 文件中,保证新 AOF 文件保存的数据库状态和服务器当前状态一致。
    • 对新的 AOF 文件进行改名,原子地覆盖现有 AOF 文件,完成新旧文件的替换
    • 继续处理客户端请求命令。

    在整个 AOF 后台重写过程中,只有信号处理函数执行时会对 Redis 主进程造成阻塞,在其他时候,AOF 后台重写都不会阻塞主进程。

     

      

  • 相关阅读:
    PHP多台服务器跨域SESSION共享
    php发送post请求到nodejs服务器
    xampp使用phpunit
    MarkdownPad 2
    php安装memcache注意事项
    yii 基础版用rbac-plus
    yii2高级版账号密码问题
    yii2 rbac-plus的使用
    manjaro-VM虚拟机vmmon错误
    Java并发包中的线程池ThreadPoolExecutor
  • 原文地址:https://www.cnblogs.com/jthr/p/14481610.html
Copyright © 2011-2022 走看看