• 04【Redis的持久化机制】


    四、Redis的持久化机制

    由于 Redis 是一个内存数据库,所谓内存数据库,就是将数据库中的内容保存在内存中,这与传统的MySQL,Oracle等关系型数据库直接将内容保存到硬盘中相比,内存数据库的读写效率比传统数据库要快的多(内存的读写效率远远大于硬盘的读写效率)。但是保存在内存中也随之带来了一个缺点,一旦断电或者宕机,那么内存数据库中的数据将会全部丢失。

    为了解决这个缺点,Redis提供了将内存数据持久化到硬盘,以及用持久化文件来恢复数据库数据的功能。Redis 支持两种形式的持久化,一种是RDB快照(snapshotting),另外一种是AOF(append-only-file)。

    1.1 RDB持久化

    RDB是Redis用来进行持久化的一种方式,是把当前内存中的数据集快照写入磁盘,也就是 Snapshot 快照(数据库中所有键值对数据)。恢复时是将快照文件直接读到内存里。

    RDB 有两种触发方式,分别是自动触发和手动触发。

    1.1.1 手动持久化

    在客户端操作时,只要执行了save命令,那么就会拍一次快照,将此次的数据全部存储到指定的文件中

    127.0.0.1:6379> save
    OK
    
    • 1
    • 2
    • 相关配置(配置文件中配置)
      • dbfilename:设置本地数据库文件名,默认值为 dump.rdb
      • dir:设置存储.rdb文件的路径
      • rdbcompression:设置存储至本地数据库时是否压缩数据,默认为 yes,采用 LZF 压缩,通常默认为开启状态,如果设置为no,可以节省 CPU 运行时间,但会使存储的文件变大(巨大)
      • rdbchecksum:默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但这样做会消耗大约10%的性能,如果希望获取到最大的性能提升,可以关闭此功能。
    bind 127.0.0.1
    port 6379
    logfile "6379.log"
    dir /root/redis-4.0.11/data
    dbfilename dump-6379.rdb
    rdbcompression no
    rdbchecksum no
    daemonize yes			# 后台启动
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1.1.2 save方法工作原理

    使用save命令:此命令会使用Redis的主线程进程同步存储,阻塞当前的Redis服务器,造成服务不可用,直到RDB过程完成。无论当前服务器数据量大小,线上不要用。

    在这里插入图片描述

    1.1.3 bgsave

    使用bgsave命令:此命令会通过fork()创建子进程,在后台进程存储。只有fork阶段会阻塞当前Redis服务器,不必到整个RDB过程结束,一般时间很短。因此Redis内部涉及到RDB都采用bgsave命令。

    127.0.0.1:6379> bgsave
    
    • 1

    在这里插入图片描述

    1.1.2 自动持久化

    一般我们是不会直接用命令生成RDB文件的,Redis支持自动触发RDB持久化机制,配置都在redis.conf文件里面。

    save seconds count
    save 900 1
    save 300 10		
    save 60 10000
    
    • 1
    • 2
    • 3
    • 4
    • seconds:持久化的时间
    • count:持久化的频率

    save 900 1:900秒持久化一次,但900秒内必须至少有1个key发生变化才会持久化。

    save 300 10:300秒持久化一次,但300秒内必须至少有10个key发生变化才会持久化。

    save 60 10000:60秒持久化一次,但60内必须至少有10000个key发送变化才会持久化。

    tips:实际开发可能会有偏差,如save 60 5,可能60秒还未到设置了5个key就发生触发一次,或者60秒内设置了4个key就触发了一次。

    自动持久化底层采用的是bgsave指令。

    • 小结:
    方式save指令bgsave指令
    读写同步异步
    阻塞客户端指令
    额外消耗内存
    启动新进程

    1.2.3 特殊情况下保存数据

    • 服务器运行过程中重启
    debug reload
    
    • 1
    • 关闭服务器时指定保存数据
    shutdown save
    
    • 1

    1.2 AOF持久化

    AOF(append only file)持久化:AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态,也就是每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。

    AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式

    1.2.1 AOF持久化的三种策略

    redis的AOF功能默认是关闭的,需要我们手动开启:

    bind 127.0.0.1
    port 6379
    logfile "6379.log"
    dir /root/redis-4.0.11/data
    rdbcompression yes
    rdbchecksum yes
    daemonize no
    appendonly yes
    appendfsync everysec
    appendfilename appendonly-6379.aof
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • appendonly

      • yes:开启aof功能
      • no:关闭aof功能(默认值)
    • appendfsync

      • always(每次):每次写入操作均同步到AOF文件中,高并发下性能较低。
      • everysec(每秒):每秒将==缓冲区==中的指令同步到AOF文件中,默认配置(如果是丢失,那么最多是这一秒)
      • no(系统控制):由操作系统控制每次同步到AOF文件的周期,一般为30s每次。
    • appendfilename:aof文件名称

    • dir:aof文件路径

    注意:AOF只会保存服务器所执行的写(set,del,add 等)的命令,对于其他对结果集并没有造成影响的命令是不会写入aof文件的。如(get、hget、lrang等)

    1.2.2 AOF重写

    AOF 持久化是通过保存被执行的写命令来记录数据库状态的,所以AOF文件的大小随着时间的流逝一定会越来越大,其中就包含了很多不必要的命令,如set某个key两次,其结果肯定为最后一次,那么前面一次的命令就没有必要再记录下来。

    为了解决此问题,Redis引入了AOF重写机制用于压缩aof文件大小,并且可以提高数据恢复的效率。

    1.2.2.1 AOF重写原理

    当执行AOF重写时,这个函数会进行大量的写入操作,所以调用这个函数的线程将被长时间的阻塞,因为Redis服务器使用单线程来处理命令请求,那么重写AOF期间,服务器将无法处理客户端发送来的命令请求;因此redis底层采用子进程的方式来将数据同步到aof文件当中。

    思考:子进程在进行AOF重写期间,服务器进程还要继续处理命令请求,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致吗?

    答:不会;

    解决方案:

    • 当子进程正在同步时,主进程接收到的所有命令将会暂时存放在重写缓冲区中,来保证子进程在工作时,主进程接收到的指令不能被保存到aof文件。

    在这里插入图片描述

    重写条件:

    • 进程内已超时的数据不再写入文件

    • 忽略无效指令,重写时使用进程内数据直接生成,这样新的AOF文件只保留最终数据的写入命令,如:

      set age 20
      set age 30
      set age 40
      
      最终合并为:
      set age 40
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 对同一数据的多条写命令合并为一条命令,如:

      rpush list a
      rpush list b
      rpush list c
      rpush list d
      
      最终合并为:
      rpush list a b c d
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    AOF重写分为两种,一种为自动重写,另一种为手动重写。

    1)手动重写

    bgrewriteaof
    
    • 1

    执行完该命令后,会发现.aof文件变小了(前提是具备重写条件)。

    2)自动重写

    条件参数:

    • auto-aof-rewrite-min-size: aof_current_size大于此参数时发生重写(默认为1MB)
    • auto-aof-rewrite-percentage: 重写百分比参数(默认百分之百)

    在redis内部会自动维护以下几个参数:

    • aof_current_size: 当前aof文件大小
    • aof_base_size: 上一次执行完重写操纵时的aof文件大小

    自动重写触发条件:

    1、aof_current_size大于auto-aof-rewrite-min-size时将会触发重写

    2、(aof_current_size-aof_base_size)/aof_base_size大于等于auto-aof-rewrite-percentage时将会触发重写。

    执行info Persistence命令,查看当前参数

    127.0.0.1:6379> info Persistence
    # Persistence
    loading:0
    rdb_changes_since_last_save:11
    rdb_bgsave_in_progress:0
    rdb_last_save_time:1585142012
    rdb_last_bgsave_status:ok
    rdb_last_bgsave_time_sec:-1
    rdb_current_bgsave_time_sec:-1
    rdb_last_cow_size:0
    aof_enabled:1
    aof_rewrite_in_progress:0
    aof_rewrite_scheduled:0
    aof_last_rewrite_time_sec:0
    aof_current_rewrite_time_sec:-1
    aof_last_bgrewrite_status:ok
    aof_last_write_status:ok
    aof_last_cow_size:6385664
    aof_current_size:138
    aof_base_size:138
    aof_pending_rewrite:0
    aof_buffer_length:0
    aof_rewrite_buffer_length:0
    aof_pending_bio_fsync:0
    aof_delayed_fsync:0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 配置自动重写redis.conf配置如下:
    bind 127.0.0.1
    port 6379
    # logfile "6379.log"
    dir /root/redis-4.0.11/data
    #dbfilename drum-6379.rdb
    #rdbcompression yes
    #rdbchecksum yes
    # save 1 1
    daemonize no
    appendonly yes
    appendfsync everysec
    appendfilename appendonly-6379.aof
    auto-aof-rewrite-min-size 100
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.3 总结

    • RDB

      • 优点
        • RDB内部存储的是redis在某个时间点的数据快照,非常适合用于数据的全量备份。
        • RDB是基于数据快照的理念设计的,每一个rdb文件都是一个已经压缩过的二进制文件,存储效率较高。
        • 由于RDB是将数据全部存储在rdb文件中,即每个rdb文件都是原始数据,在恢复大数据集时的速度比 AOF 的恢复速度要快的多。
      • 缺点:
        • 如果对数据恢复非常敏感,那么RDB的持久化效率将没有AOF的高,虽然RDB可以设置保存点save,但是因为RDB每次拍摄数据快照需要将此次数据快照的所有数据都写入rdb文件,如果频率过高,那么性能势必大大下降。因此RDB无法做到实时持久化(或者换一个方式说,RDB不适合做实时的持久化)。
        • RDB持久化方式并没有缓冲区的概念,如果rdb的子进程正在将数据写入到rdb文件,会导致数据库的数据和rdb文件中保存的数据不一致。
        • Redis的众多版本中未进行RDB文件格式的版本统一,有可能出现各版本服务之间数据格式无法兼容现象。
    • AOF

      • 优点

        • AOF是基于日志形式的理念设计的,AOF将每一个操作指令的步骤以日志的方式记录下来,因此同步的频率相对RDB来说可以非常的频繁。AOF适用于数据实时同步要求较高的场合。
        • AOF具有重写机制,可以有效的整理不必要的指令来压缩aof文件的大小,提升数据恢复的性能。
        • AOF 文件有序地保存了对数据库执行的所有写入操作,这些写入命令被redis保存到了aof文件上,这些指令让人可以轻松阅读,并且文件易于解析,当你中途不小心执行了flushall指令,只要aof文件没有被重写,此时可以编辑aof文件删除flushall指令,来恢复数据:
      • *1
        $7
        flushdb
        
        • 1
        • 2
        • 3

        删除以上数据,进行AOF恢复;

      • 缺点

        • 对于同等的数据量,AOF 文件的体积通常要大于 RDB 文件的体积。
        • 由于aof文件保存的是操作的命令,因此恢复起来速度要比RDB慢

  • 相关阅读:
    从手工测试转自动化测试前,你必须知道的9大内容
    flink 运行方式和部署模式
    Android A13 CTS 测试问题部分总结
    二、vmware配置集群分发,配置java环境
    联邦学习中的优化算法
    mapbox支持的坐标系
    arm-2d库详细介绍
    【quartus13.1/Verilog】swjtu西南交大:计组课程设计
    【STM32】CRC(循环冗余校验)
    中国聚异丁烯市场研究与投资价值报告(2022版)
  • 原文地址:https://blog.csdn.net/Bb15070047748/article/details/125433796