暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Redis 核心要领-数据库持久化

码上Javaer 2025-03-05
145


Redis与传统数据库的一个主要区别在于,Redis把所有数据都存储在内存中,而传统数据库通常只会把数据的索引存储在内存中,并将实际的数据存储在磁盘上。由于内存数据易失存储(volatile storage),它记录的数据在系统断电之后就会丢失,这对于想把Redis用作数据库而不仅仅是缓存的用户来说是不愿意看到的

1 RDB 持久化

RDB持久化是Redis默认使用的持久化功能,该功能创建一个经过压缩的二进制文件,其中包含服务器在各个数据库中存储的键值对数据等信息。RDB持久化创建的文件都是以.rdb后缀结尾,其中rdb代表Redis Database

1.1 SAVE:阻塞服务器并创建rdb文件

通过执行SAVE命令,要求Redis服务器以同步方式创建一个rdb文件。

    127.0.0.1:6379> save
    OK

    SAVE执行期间,服务器将阻塞,知道RDB文件创建完成。如果执行SAVE命令时已经有了RDB文件,那服务器将使用新的RDB文件替换已有的RDB文件,过程如下:

    1.2 BGSAVE:以非阻塞方式创建RDB文件

    SAVE命令在执行时会阻塞服务器,所以在此期间服务器将无法为其他客户端提供服务。为解决这个问题,Redis提供了SAVE的异步版本BGSAVE命令

    BGSAVE 执行流程如下:

      1)创建一个子进程
      2)子进程执行SAVE命令,创建新的RDB文件
      3)RDB文件创建完毕后,子进程退出并通知Redis服务器进程(父进程)新RDB文件已经完成
      4)Redis服务器进程进行新RDB文件替换已有的RDB文件

      整体流程如下图:

      1.3 通过配置选项自动创建RDB文件

      除了SAVE和BGSAVE命令手动创建RDB文件外,还可以通过save选项,让Redis服务器在满足指定条件时自动执行BGSAVE命令

        save <seconds> <changes>

        说明:

          seconds: 指定触发持久化操作所需的时长
          changes:指定触发持久化操作所需的修改次数

          示例:

          save 60 10000, 表示:满足”服务器在60s内执行了10000次修改“条件时,服务器自动执行BGSAVE命令

          1.3.1 使用多个save命令

            save 6000 1
            save 600 100
            save 60 10000

            表示当满足以下任意条件时,服务器就会执行BGSAVE命令

            • 6000s内,服务器对数据库执行了至少1次修改

            • 600s内,服务器对数据库执行了至少100次修改

            • 60s内,服务器对数据库执行了至少10000次修改


            1.3.2 默认配置

            如果没有显示关闭RDB持久化功能,也没有启用AOF持久化功能,那么save选项默认配置如下:

              save 60 10000
              save 300 100
              save 3600 1

              1.4 SAVE和BGSAVE的选择

              SAVE命令会阻塞服务器,如果想创建RDB期间同时为其他客户端服务,那只能使用BGSAVE命令来创建RDB文件。

              SAVE无需创建子进程,不会消耗额外内存,所以在离线Redis服务器时,SAVE命令效率比BGSAVE更高

              1.5 RDB文件结构

              1.5.1 总体结构

              • RDB文件标识符文件最开头是RDB文件标识符,内容是”REDIS“5个字符。在加载RDB文件时会快速判断该文件是否为真正的RDB文件

              • 版本号字符串格式的数字,长度为4个字节。

              • 设备附加信息记录Redis服务器以及所在平台的信息

              • 数据库数据记录了Redis数据库存储的0个或任意多个数据库的数据。按照数据库号码从小到大进行排序

              • Lua脚本缓存如果Redis启用了复制功能,则该部分保存所有已被缓存的Lua脚本。

              • EOF标识RDB文件的末尾,实际值为二进制0xFF,当Redis读取到EOF时,则标识正文已全部读取完毕了

              • CRC64校验和RDB文件末尾是一个以无符号64位整数标识CRC64校验和。Redis在读取RDB文件时能快速检查RDB文件是否有出错或者损坏情况

              1.5.2 数据库信息结构

              • 数据库号码:比如0

              • 键值对总数量

              • 带有过期时间的键值对数量

              • 键值对数据部分:RDB文件将以无序方式记录数据库包含的所有键值对。详情参考下节

              1.5.3 键值对数据部分

              • 过期时间:每个键值对开头记录的是可能存在的过期时间,是毫秒级精度的UNIX时间戳

              • LRU信息&LFU信息:分别用户实现可选的LRU算法和LFU算法,因为Redis只能选择一个键淘汰算法,所以两项不会同时出现,最多只会出现其中一种。

              • 最后三个部分则记录键值对的类型(字符串,列表,散列等)以及键和值。

              2 AOF 持久化

              与全量式的RDB持久化不同,AOF提供的是增量的持久化功能,核心原理:服务器每次执行完写命令后,会以协议文本的方式将被执行的命令追加到AOF文件的末尾。

              1. 打开AOF持久化功能

              用户可以通过服务器的appendonly选项来决定是否打开AOF功能:

                appendonly <value>
                // 说明
                value:yes(打开aof),no(关闭aof)

                2. 设置AOF文件的冲洗频率

                为了提高写入性能,OS通常会把针对磁盘的多次写操作优化为一次写操作。当执行写操作时,先将数据写入到内存的缓存中,等到指定的时限或满足某些写入条件时,系统才会执行flush系统调用,将缓冲区的数据冲洗到硬盘。

                Redis提供了appendfsync选项来控制冲洗AOF文件的频率

                  appendfsync <value>

                  value:

                  • always:每执行一个写命令,就对AOF文件执行一次冲洗操作

                  • everysec:每隔1s,就对AOF执行一次冲洗操作

                  • no:不主动对AOF文件执行冲洗操作,由OS决定何时对AOF进行冲洗

                  3. AOF 重写

                  随着服务器不断运行,执行的命令也越来越多,AOF文件也会越来越大,同时,如果对相同键执行多次修改,那AOF文件中还会出现多个冗余命令。为了减少冗余命令,让AOF文件保持“苗条”,并提供数据恢复操作的执行速度,Redis提供了AOF文件重写功能,该功能生成一个全新的AOF文件,并且只包含恢复当前数据库所需的尽可能少的命令。

                  3.1 BGREWRITEAOF 命令

                  用户可以通过执行BGREWRITEAOF命令显示触发AOF重写操作,该命令是无参命令

                    127.0.0.1:6379> BGREWRITEAOF
                    Background append only file rewriting started

                    该命令执行流程如下:

                    注意:如果发送该命令时,服务器正在创建RDB文件,那服务器会在RDB文件创建完成后再执行AOF重写操作。从而避免两个写磁盘同时执行导致机器性能下降;其次,服务器在执行AOF重写过程中,再次执行该操作,则服务器会返回错误

                    3.2 AOF重写配置选项

                    除了BGREWRITEAOF手动执行命令之外,还可以通过设置下面两个配置项让服务器自动触发BGREWRITEAOF命令

                      auto-aof-rewrite-min-size <value>


                      auto-aof-rewrite-percentage <value>

                      说明:

                      • auto-aof-rewrite-min-size:执行触发AOF重写的最小AOF文件体积,当小于给定值时,不会执行AOF重写。默认值为64m

                      • auto-aof-rewrite-percentage:触发AOF重写所需的文件体积增大比例

                      3.3 AOF持久化优缺点

                      优点:AOF持久化安全性较高,通过everysec选项,用户可以将数据丢失的时间窗口限制在1s以内

                      缺点:

                      • AOF文件是协议文本,体积要比RDB文件大得多,生成AOF文件时间也较长

                      • RDB持久化数据恢复速度比AOF持久化恢复速度快得多,并且数据体积越大,两者之间的差异就越明显

                      3 RDB-AOF 混合持久化

                      Redis 的两种持久化方式(RDB和AOF),都有各自的优点和缺点

                      • RDB持久化可以生产紧凑的RDB文件,使用RDB文件进行数据恢复速度也很快,但RDB的全量持久化可能会让服务器在停机时丢失大量数据

                      • AOF持久化可以将丢失数据的时间窗口限制在1s之内,但AOF文件体积要比RDB文件大的多,并且数据恢复速度相对较慢

                      RDB-AOF混合持久化模式是基于AOF持久化模式构建而来-如果用户打开了AOF持久化后,并且将 aof-use-rdb-preamble <value> 设置为yes时,那么Redis在执行AOF重写时,就会像BGSAVE命令那样生成RDB数据,并将这些数据写入新建AOF文件中,其他AOF重写开始之后的命令将会以追加方式到AOF文件的末尾。

                      RDB-AOF文件格式如下:

                      Redis载入AOF文件时执行的判断流程



                      感谢大家阅读本篇文章,希望以上内容能对大家有所帮助。如果你有任何疑问或者建议,欢迎在评论区留言交流。同时,别忘了点击下方的 “在看” 和 “分享”,让更多的程序员朋友受益。后续我们还会分享更多精彩的编程知识和经验,敬请关注!



                      文章转载自码上Javaer,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                      评论