Redis持久化存储

作者: _str_ | 来源:发表于2019-11-25 21:08 被阅读0次

    1. 持久化存储的方式介绍

    Redis 分别提供了 RDB 和 AOF 两种持久化机制:

    • RDB 将数据库的快照(snapshot)以二进制的方式保存到磁盘中。

    • AOF 则以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件,以此达到记录数据库状态的目的。

    2. RDB

    快照方式持久化

    快照方式持久化就是在某时刻把所有数据进行完整备份

    a. 什么是RDB

    和 MySQL 中的 mysqldump 差不多一个道理。

    image

    b. 什么情况下会触发 RDB

    第一种情况,主动执行 save 命令(同步,阻塞 ,就是save 命令执行完毕后才能执行后续的其他命令操作)

    image

    阻塞

    image
    保存 RDB 文件的策略

    每次创建新的文件,并且替换原来旧文件(假如存在旧的文件)

    第二种情况,主动执行 bgsave 命令 (异步,非阻塞 )

    image
    • 文件策略和 save 相同

    第三种情况,自动触发

    自动触发,就是通过对 Redis 的配置文件重相关选项的修改,当达到某个配置好的条件后,自动生成 RDB 文件
    ,其内部使用的是 bgsave 命令。

    配置文件中相关选项的默认值如下表:

    配置 seconds changes 含义
    save 900 1 每隔 900 秒检查一次,假如至少有 1 条数据改变,就生成新的 RDB 文件
    save 300 10 每隔 300 秒检查一次,假如至少有 10 条数据改变,就生成新的 RDB 文件
    save 60 10000 每隔 60 秒检查一次,假如至少有 10000 条数据改变,就生成新的 RDB 文件

    每次检查都会建立一个新的检查点,以便用于下次检查作为参考信息。

    关于 RDB 文件的配置信息

    默认文件名
    dbfilename dump.rdb

    默认文件保存位置
    dir ./

    假如 bgsave 执行中发生错误,是否停止写入,默认是 yes , 表示假如出错,就停止写入。
    stop-writes-on-bgsave-error yes

    是否使用压缩|
    rdbcompression yes

    是否进行数据的校验
    rdbchecksum yes

    建议的最佳配置

    关闭自动生成 RDB 文件
    在配置文件中注释掉如下内容

    #save 900 1
    #save 300 10
    #save 60    10000
    
    

    使用不同端口号进行区分,因为,有可能会在同一台主机上开启多个 Redis 实例。
    防止多个实例产生的数据信息写到一个文件中。
    dbfilename dump-${port}.rdb
    这里我将它修改成dump-6379.rdb

    指定一个大硬盘的路径
    dir /redis_data

    假如出现错误,停止继续写入
    stop-writes-on-bgsave-error yes

    采用压缩
    rdbcompression yes

    进行校验
    rdbchecksum yes

    实验

    修改配置文件中的相关选项,使其成为如下内容中显示的值:

    dbfilename dump-6379.rdb
    dir /redis_data   # 此目录需要自己创建
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    
    

    假如你的 Redis 服务器允许客户端可以从非本机访问,应该在配置文件中,把 protected-mode 的值设置问 no

    这样的话,客户端就可以从其他主机访问 Redis 服务器了,并且不需要密码。

    重启服务后,在 Rdis 命令行客户端中输入 save 命令。

    [root@s1 ~]# redis-cli
    127.0.0.1:6379> save
    OK
    127.0.0.1:6379>
    
    

    该命令将在配置文件重配置的指定目录中创建 dump-6379.rdb文件。

    恢复数据时,只需要保证此文件完好,并且在配置文件中指定的目录下即可。这样 Rdis 启动时就会把此文件中的数据恢复到当前的服务器中。

    bgsave 命令和 save基本一样,就是 bgsave 命令不会产生阻塞

    127.0.0.1:6379> bgsave
    Background saving started
    127.0.0.1:6379>
    
    

    查看当前服务器的数据文件目录

    127.0.0.1:6379> CONFIG GET dir
    1) "dir"
    2) "/"
    

    3、使用supervior后台管理redis

    编写supervisor的配置文件

    vi /etc/supervisord.d/redis.ini
    [program:qfcmdb]
    ;执行的命令
    command=/usr/bin/redis-server /etc/redis/6379.conf
    priority=999                ; 优先级(越小越优先)
    autostart=true              ; supervisord启动时,该程序也启动
    autorestart=true            ; 异常退出时,自动启动
    startsecs=10                ; 启动后持续10s后未发生异常,才表示启动成功
    startretries=3              ; 异常后,自动重启次数
    exitcodes=0,2               ; exit异常抛出的是0、2时才认为是异常
    stopsignal=QUIT             ; 杀进程的信号
    
    ; 在程序发送stopignal后,等待操作系统将SIGCHLD返回给supervisord的秒数。
    ; 如果在supervisord从进程接收到SIGCHLD之前经过了这个秒数,
    ; supervisord将尝试用最终的SIGKILL杀死它
    stopwaitsecs=1
    user=root                   ; 设置启动该程序的用户
    log_stdout=true             ; 如果为True,则记录程序日志
    log_stderr=false            ; 如果为True,则记录程序错误日志
    logfile=/var/log/redis-6379.log    ; 程序日志路径
    logfile_maxbytes=1MB        ; 日志文件最大大小
    logfile_backups=3          ; 日志文件最大数量
    
    [include]
    files = relative/directory/*.ini
    

    启动supervisor

    启动时配置文件的默认查找顺序
    • $CWD/supervisord.conf
    • $CWD/etc/supervisord.conf
    • /etc/supervisord.conf
    • /etc/supervisor/supervisord.conf (在 Supervisor 3.3.0 中及更改版本)
    • ../etc/supervisord.conf(相对于被管理程序的可执行文件)
    • ../supervisord.conf (相对于被管理程序的可执行文件)
    查看任务 image.png

    4、AOF

    写日志方式持久化

    写日志方式持久化就是把用户执行的所有写指令(增删改)备份到文件中,还原数据时只需要把备份的所有指令重新执行一遍即可

    什么是 AOF

    AOF 文件保存了 Redis 的数据库状态, 而文件里面包含的都是符合 Redis 通讯协议格式的命令文本。

    image

    AOF 保存的模式

    Redis 目前支持三种 AOF 保存模式,它们分别是:

    1. AOF_FSYNC_NO :不保存。
    2. AOF_FSYNC_EVERYSEC :每一秒钟保存一次。(生产中一般选这种)
    3. AOF_FSYNC_ALWAYS :每执行一个命令保存一次

    不保存

    在这种模式下, SAVE 只会在以下任意一种情况中被执行:

    Redis 被关闭
    AOF 功能被关闭
    系统的写缓存被刷新(可能是缓存已经被写满,或者定期保存操作被执行)
    这三种情况下的 SAVE 操作都会引起 Redis 主进程阻塞。

    每执行一个命令保存一次

    在这种模式下,每次执行完一个命令之后, WRITE 和 SAVE 都会被执行。

    另外,因为 SAVE 是由 Redis 主进程执行的,所以在 SAVE 执行期间,主进程会被阻塞,不能接受命令请求。

    AOF 三种保存模式的比较

    因为阻塞操作会让 Redis 主进程无法持续处理请求, 所以一般说来, 阻塞操作执行得越少、完成得越快, Redis 的性能就越好。

    模式 1 的保存操作只会在AOF 关闭或 Redis 关闭时执行, 或者由操作系统触发, 在一般情况下, 这种模式只需要为写入阻塞, 因此它的写入性能要比后面两种模式要高, 当然, 这种性能的提高是以降低安全性为代价的: 在这种模式下, 如果运行的中途发生停机, 那么丢失数据的数量由操作系统的缓存冲洗策略决定。

    模式 2 在性能方面要优于模式 3 , 并且在通常情况下, 这种模式最多丢失不多于 2 秒的数据, 所以它的安全性要高于模式 1 , 这是一种兼顾性能和安全性的保存方案。

    模式 3 的安全性是最高的, 但性能也是最差的, 因为服务器必须阻塞直到命令信息被写入并保存到磁盘之后, 才能继续处理请求。

    综合起来,三种 AOF 模式的操作特性可以总结如下:

    模式 WRITE 是否阻塞? SAVE 是否阻塞? 停机时丢失的数据量
    AOF_FSYNC_NO 阻塞 阻塞 操作系统最后一次对 AOF 文件触发 SAVE 操作之后的数据。
    AOF_FSYNC_EVERYSEC 阻塞 不阻塞 一般情况下不超过 2 秒钟的数据。
    AOF_FSYNC_ALWAYS 阻塞 阻塞 最多只丢失一个命令的数据。

    AOF 方式下的数据还原

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

    创建一个不带网络连接的伪客户端(fake client)。
    读取 AOF 所保存的文本,并根据内容还原出命令、命令的参数以及命令的个数。
    根据命令、命令的参数和命令的个数,使用伪客户端执行该命令。
    执行 2 和 3 ,直到 AOF 文件中的所有命令执行完毕。
    完成第 4 步之后, AOF 文件所保存的数据库就会被完整地还原出来。

    注意, 因为 Redis 的命令只能在客户端的上下文中被执行, 而 AOF 还原时所使用的命令来自于 AOF 文件, 而不是网络, 所以程序使用了一个没有网络连接的伪客户端来执行命令。

    当程序读入这个 AOF 文件时, 它首先执行 SELECT 0 命令 —— 这个 SELECT 命令是由 AOF 写入程序自动生成的, 它确保程序可以将数据还原到正确的数据库上。

    注意:
    为了避免对数据的完整性产生影响, 在服务器载入数据的过程中, 只有和数据库无关的订阅与发布功能可以正常使用, 其他命令一律返回错误。

    AOF 的重写机制

    为什么需要重写机制

    AOF 文件通过同步 Redis 服务器所执行的命令, 从而实现了数据库状态的记录, 但是, 这种同步方式会造成一个问题: 随着运行时间的流逝, AOF 文件会变得越来越大。

    1. 对同一个键的状态的多次不同操作,而最终得到一个结果。比如对列表的添加删除元素。

    2. 被频繁操作的键。比如累加

    重新机制是如何实现的

    实际上, AOF 重写并不需要对原有的 AOF 文件进行任何写入和读取, 它针对的是数据库中键的当前值,也就是源数据从目前的内存中获取。

    考虑这样一个情况, 如果服务器对键 list 执行了以下四条命令:

    RPUSH list 1 2 3 4      // [1, 2, 3, 4]
    
    RPOP list               // [1, 2, 3]
    
    LPOP list               // [2, 3]
    
    LPUSH list 1            // [1, 2, 3]
    
    

    那么当前列表键 list 在数据库中的值就为 [1, 2, 3] 。

    如果我们要保存这个列表的当前状态, 并且尽量减少所使用的命令数, 那么最简单的方式不是去 AOF 文件上分析前面执行的四条命令, 而是直接读取 list 键在数据库的当前值, 然后用一条 RPUSH 1 2 3 命令来代替前面的四条命令。

    除了列表之外,集合、字符串、有序集、哈希表等键也可以用类似的方法来保存状态。

    根据键的类型, 使用适当的写入命令来重现键的当前值, 这就是 AOF 重写的实现原理。

    基本都步骤

    for  遍历所有数据库:
          if  如果数据库为空:
                 那么跳过这个数据库
          else:
                写入 SELECT 命令,用于切换数据库
                for  选择一个库后,遍历这个库的所有键
                       if 如果键带有过期时间,并且已经过期,那么跳过这个键
                       if 根据数据的类型,进行相关操作。
    
    

    AOF 重写的实现方式

    方式 区别
    bgrewriteaof 命令 不需要重启服务,不便于统一管理
    配置文件实现 需要重启服务,便于进行统一管理

    bgrewriteaof

    image

    配置文件实现

    image
    触发条件,必须同时满足如下条件
    image

    aof_current_sizeaof_base_size 可以通过命令 info persistence 查看到

    重写流程图

    image

    对于上图有四个关键点补充一下:

    在重写期间,由于主进程依然在响应命令,为了保证最终备份的完整性;因此它依然会写入旧的AOF file中,如果重写失败,能够保证数据不丢失。当然这个是可以通过配置来决定在重写期间是否进行主进程普通的 AOF 操作。
    为了把重写期间响应的写入信息也写入到新的文件中,因此也会为子进程保留一个buf,防止新写的file丢失数据。
    重写是直接把当前内存的数据生成对应命令,并不需要读取老的AOF文件进行分析、命令合并。
    AOF文件直接采用的文本协议,主要是兼容性好、追加方便、可读性高可认为修改修复。

    注意:无论是RDB还是AOF都是先写入一个临时文件,然后通过 rename 完成文件的替换工作。

    配置示例

    // 要想使用 AOF 的全部功能,需要设置为  yes
    appendonly yes
    
    // AOF 文件名,路径才看之前的 `dir` 配置项
    appendfilename "appendonly.aof"
    //这里我使用的名字是 `appendonly-6379.aof`
    
    // 平常普通的 AOF 的策略
    appendfsync everysec
    
    // 当执行 AOF 重写时,是否继续执行平常普通的 AOF 操作。
    // 这里设置文件  yes , 表示不执行
    // 因为假如,同时执行,两种操作都会对磁盘 I/O 进行访问,造成
    // I/O 访问量过大,产生性能衰减
    no-appendfsync-on-rewrite yes
    
    // AOF 文件容量的增长率
    auto-aof-rewrite-percentage 100
    
    // AOF 文件的最低容量,就是当前文件的大小大于此值时,就会进行重写。当然这只是其中一个条件。
    auto-aof-rewrite-min-size 64mb
    
    

    也可以 在命令行里进行修改 以便快速生效

    [root@s1 ~]# redis-cli
    127.0.0.1:6379> config get appendonly
    1) "appendonly"
    2) "no"
    127.0.0.1:6379> config set appendonly yes
    OK
    127.0.0.1:6379> config get appendonly
    1) "appendonly"
    2) "yes"
    

    重写机制补充

    基本上就是修改配置文件就可以生效

    触发它的重写命令 或者手动触发的时候 还能够执行普通的操作 也就是继续往数据库中写值,其中可以是一样的key也可以是其他的 但是只会把执行重写命令之前的数据进行重写 之后的会每秒异步存储到磁盘上

    image.png image.png image.png image.png

    AOF和RDB的区别

    image.png

    相关文章

      网友评论

        本文标题:Redis持久化存储

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