03-Redis 持久化-RDB

RDB持久化

  • RDB文件是一个压缩的二进制文件,redis数据库将自己的状态生成一个RDB文件,通过这个文件也可以还原对应时刻数据库的状态。

一、RDB文件的创建与载入

1.1 创建

  • save:创建RDB文件,期间会阻塞redis不能处理任何请求
  • bgsave:创建子进程生成RDB文件,父进程可以继续处理请求

1.2 载入

  • 服务器启动时自动载入RDB文件,无需命令调用,载入过程服务器是阻塞状态,直到载入完成

1.3 优先级

  • AOF的更新频率通常高于RDB,因此在开启了AOF的情况下,服务器优先使用AOF还原数据库,只有在关闭AOF的情况下,才会使用RDB来还原数据库状态

1.4 BGSAVE

  • 在执行BGSAVE期间,服务器会拒绝SAVE和BGSAVE命令,避免多个进程创建RDB文件。
  • BGSAVE和BGREWRITEAOF不能同时执行,执行一个时,收到另一个命令请求会拒绝,考虑到两个命令都会大量读写磁盘。

二、save配置

  • 通过配置save选项来通过条件触发执行BGSAVE命令,如下:
save 900 1
save 300 10
save 60 10000
  • 这表示三个条件任意一个被满足,将执行BGSAVE。900秒内至少一次修改,300秒内至少十次修改,60秒内至少10000次修改,上面也是默认配置

  • save选项原理:服务器会周期性(100ms间隔)检查三个条件,内部会保存一个计数器和上一次执行BGSAVE的Unix时间戳,如果时间到了一个条件的临界值,并且计数器记录的命令修改次数也已经达到了,就会执行BGSAVE,并且将计数器清零,更新BGSAVE命令执行时间。注意这里时间没到的话,即使执行的命令次数到了也不会触发,比如60秒内10000次,假如过去了40秒,但是期间修改了10001次,也不会触发,时间和次数是必须同时满足的(反过来想如果不是这样的话,那么比如10秒内执行2次命令,那么肯定就需要执行BGSAVE了,因为这就满足了第一个条件了),因此也可以认为,BGSAVE默认情况下,最快也只能60秒调用一次,频率不会再快了,即使更新次数更快也要等到60秒,如果有至少一次操作的话,最慢是900秒。我们看下面的redis源码就知道时间和次数是逻辑与的关系,这里面判断的时候,修改次数和时间必须同时达到才会执行BGSAVE;

    //源码文件redis.c的serverCron函数
    // 遍历所有保存条件,看是否需要执行 BGSAVE 命令
         for (j = 0; j < server.saveparamslen; j++) {
            struct saveparam *sp = server.saveparams+j;

            /* Save if we reached the given amount of changes,
             * the given amount of seconds, and if the latest bgsave was
             * successful or if, in case of an error, at least
             * REDIS_BGSAVE_RETRY_DELAY seconds already elapsed. */
            // 检查是否有某个保存条件已经满足了
            if (server.dirty >= sp->changes &&
                server.unixtime-server.lastsave > sp->seconds &&
                (server.unixtime-server.lastbgsave_try >
                 REDIS_BGSAVE_RETRY_DELAY ||
                 server.lastbgsave_status == REDIS_OK))
            {
                redisLog(REDIS_NOTICE,"%d changes in %d seconds. Saving...",
                    sp->changes, (int)sp->seconds);
                // 执行 BGSAVE
                rdbSaveBackground(server.rdb_filename);
                break;
            }
         }
  • 注释掉前面的三项配置,或者添加save ""配置,即可禁用RDB,具体可以参考redis配置文件注释
################################ 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 ""

save 900 1
save 300 10
save 60 10000

三、RDB文件结构

3.1 RDB文件组成部分

字段组成长度
redis字符常量5字节
版本号4字节
数据库键值对长度不定,可以为空
EOF,结束标志1字节
校验和8字节

3.2 RDB的数据库键值对

  • 数据库部分是最核心的,其他的部分都是固定的或者长度固定的。数据库部分可以包含0或者多个数据库的信息,每个数据库的信息是相邻且独立的。
  • 每一个数据库的信息包括三部分,包括selectdb,dbnumber,k–v对。第一和二部分用于选择数据库,第三部分是真正的数据。
selectdbdbnumberk–v

3.3 k-v对部分

  • k-v对部分保存一个或者多个键值对,可以携带过期时间。因为数据类型的不一样,这部分的长度也有不同,因此它也进行了细分。
  • 每一个k-v对部分由一下几个部分组成。
EXPIRETIME_MSmsTYPEkeyvalue
EXPIRETIME_MS:代表后面是一个毫秒的时间,长度为1字节
ms:是unix的时间戳,8字节
TYPE:数据类型
后面是键值对

四、分析RDB文件

  • RBD文件是redis用于恢复自身数据的,我们来看看其使用方法

4.1 查看方法

  • 使用Linux下的od命令可以查看RDB文件,使用-c参数可以指定编码方式为ASCII,-x指定为十六进制

4.2 查看RDB文件

  • 先生成RDB文件
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SAVE
OK
127.0.0.1:6379> 
  • 保存一个name=mozping的键值对后,再生成新的RDB文件。对比查看空的数据库和保存了键值对的数据库,两个RDB文件的区别
mzpdeMac-mini:redis-4.0.14 mzp$ od -c dump.rdb 
0000000    R   E   D   I   S   0   0   0   8 372  \t   r   e   d   i   s
0000020    -   v   e   r 006   4   .   0   .   1   4 372  \n   r   e   d
0000040    i   s   -   b   i   t   s 300   @ 372 005   c   t   i   m   e
0000060  302 376   b 004   ] 372  \b   u   s   e   d   -   m   e   m 302
0000100    0 274 017  \0 372  \f   a   o   f   -   p   r   e   a   m   b
0000120    l   e 300  \0 377   u  \a 277   { 277   B 301 372            
0000135
mzpdeMac-mini:redis-4.0.14 mzp$ rm ./dump.rdb 
mzpdeMac-mini:redis-4.0.14 mzp$ od -c dump.rdb 
0000000    R   E   D   I   S   0   0   0   8 372  \t   r   e   d   i   s
0000020    -   v   e   r 006   4   .   0   .   1   4 372  \n   r   e   d
0000040    i   s   -   b   i   t   s 300   @ 372 005   c   t   i   m   e
0000060  302 257   c 004   ] 372  \b   u   s   e   d   -   m   e   m 302
0000100  240 274 017  \0 372  \f   a   o   f   -   p   r   e   a   m   b
0000120    l   e 300  \0 376  \0 373 001  \0  \0 004   n   a   m   e  \a
0000140    m   o   z   p   i   n   g 377   N 222 274 016   ` 365   l 224
0000160
mzpdeMac-mini:redis-4.0.14 mzp$ 
  • 可以看到最开始的是REDIS这个常量,5字节,后面的008代表版本,后面也可以看到键值对的信息。这里我查看的
    RDB是redis4.0.14版本的,前面的资料是源于《REDIS设计与实现》这本书,基于的版本较低稍微有点不一样。不过对于
    普通使用来说一般不会要深入了解RDB文件的结构,如果需要的话可以寻找更多资料。

4.3 RDB工具

  • redis-check-dump是redis自带的RDB文件分析工具。
mzpdeMac-mini:redis-4.0.14 mzp$ ./bin/redis-check-rdb   ./dump.rdb 
[offset 0] Checking RDB file ./dump.rdb
[offset 27] AUX FIELD redis-ver = '4.0.14'
[offset 41] AUX FIELD redis-bits = '64'
[offset 53] AUX FIELD ctime = '1560569706'
[offset 68] AUX FIELD used-mem = '1030304'
[offset 84] AUX FIELD aof-preamble = '0'
[offset 86] Selecting DB ID 0
[offset 112] Checksum OK
[offset 112] \o/ RDB looks OK! \o/
[info] 1 keys read
[info] 0 expires
[info] 0 already expired
  • 从这里的信息我们可以看到,4.0.14版本的redis在RDB文件中包含的信息比之前分析的要多一些,比如redis-bit,ctime,used-men这样的信息。

4.4 恢复RDB

  • 默认情况下,redis启动就会找到对应的RDB文件将数据库进行恢复,这里我们需要关注redis的2个配置
# The filename where to dump the DB,
#这是RDB文件的名字,默认是dump.rdb
dbfilename dump.rdb

#这是RDB文件和AOF文件保存的路径,默认是当前路径
# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir ./
配置作用默认值
dbfilenameRDB文件的文件名称dump.rdb
dirRDB和AOF文件的保存路径,要配置路径而不是文件安装的当前路径
  • 如果强制杀掉redis,那么内存中的数据可能来不及持久化,再次启动恢复数据会有部分丢失
  • 使用redis-cli shutdown是安全关闭redis,会将数据持久化之后再关闭
  • 如果关闭redis后删除了RDB文件,再次启动redis数据会丢失
  • 如果关闭redis后,用一个新的RDB文件替换旧的RDB文件,那么启动后会恢复新的RDB中的数据,不过最好版本一致,因为这些信息都在RDB里面。
我验证了安全关闭redis后,重新启动redis,数据是在的。但是我关闭redis,然后把RDB文件移动到另一个A路径,
再启动redis,就没有数据了,因为找不到RDB文件。然后我再修改redis的配置文件将dir配置修改为A路径,然后再
启动redis,数据又有了,按照这个思路可以使用指定的RDB文件恢复redis的数据

五、小结

  • 我们简单了解了redis的RDB持久化方法,包括RDB的创建方法,配置,备份时机,文件结构,恢复方法。
  • 下一篇文章我们开始AOP的持久化方法。

六、参考

  • [REDIS设计与实现]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值