zoukankan      html  css  js  c++  java
  • Redis持久化之RDB&&AOF的区别

    在说Redis持久化之前,需要搞明白什么是数据库状态这个概念,因为持久化的就是将内存中的数据库状态保存到磁盘上。那么什么是数据库状态呢?Redis是一个key-value数据库服务器,一般默认是有16个数据库,可以使用select <index>命令进行切换(0-15),这每个非空的数据库又可以包含任意多个键值对,为了方便起见,我们将数据库服务器中的非空数据库以及它们的键值对通常为【数据库状态】,所以这里持久化,说的不是一个数据库,而是服务器上的所有非空数据库。

    接着,我们继续来说redis的两种持久化方式,一种是RDB持久化,一种是AOF持久化,这两种持久化方式都可以将内存中的数据库状态保存到磁盘上,但是原理非常不同,我们逐一来看看,首先说一下RDB持久化。

    RDB持久化默认生成的文件名为dump.rdb,这个可以通过配置文件配置,RDB文件一个经过压缩的二进制文件,接下来介绍一些rdb文件结构,RDB文件包含五个部分,分别是【Redis |  db_version  |  databases | EOF | check_sum】开头的Redis表示这是一个RDB文件,服务器可以通过这个快速检查载入的文件是否是rdb文件,db_version是一个整数,代表RDB文件的版本,databases部分包含0个或者是任意多个数据库,以及数据库中的键值对数据,如果数据库状态是空,那么这部分也是空的,这部分的结构如下【SELECTDB | db_number | key_values_pairs】其中SELECTDB是一个常量,长度是一字节,当服务器遇到这个的时候,知道接下来要读入的将是一个数据库号码,db_number中保存的是一个数据库号码(0-15)这两部分结合就可以切换到相应的数据库,然后读取键值对了,键值对的部分的结构有两种,一种是带过期值的,一种是不带过期值的,如果是带过期值,那么结构是【EXPIRETIME_MS | ms |  TYPE | key | value】第一个常量和SELECTDB一样,第二部分是毫秒为单位的UNIX时间戳,就是键值对的过期时间,然后是TYPE记录了value的类型,是String,list,set,zset,hash,等。不带过期值的键值对部分的结构没有前两部分,只是【TYPE | key | value】

    RDB持久化可以通过命令进行手动执行,也可以配置好后让服务器自动执行,手动执行可以使用Redis命令【SAVE】或者【BGSAVE】,这两个命令有一些差别,需要说明一下,save命令会阻塞服务器进程,也就说,但save命令执行的时候服务器不能够处理任何命令请求,知道save命令执行完毕,RDB文件创建完毕,bgsave命令不会阻塞服务器,而是通过派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程继续处理命令请求,这里需要说明一下,bgsave处理期间,服务器进程虽然能够继续处理命令请求,但是save,bgsave,bgrewriteaof这三个命令的处理方式会和平时有所不同,在bgsave期间,save命令会被服务器拒绝,服务器禁止save和bgsave同时执行,避免父进程和子进程同时执行两个rdbSave(创建RDB文件的实际工作实际上是由rdbSave函数完成,save和bgsave都会调用这个函数,只是调用的方式不同)调用,bgsave命令在bgsave期间也会被拒绝,理由和拒绝save的理由一样,两个bgsave也会产生竞争,bgrewriteaof命令会被延迟到bgsave执行完毕之后执行。

    Redis没有专门的RDB文件载入命令,只要Redis服务器开启,就会检测RDB文件是否存在,就会自动载入RDB文件,这里需要说明一点,如果服务器开启了AOF持久化功能,服务器会优先使用AOF文件来还原数据库状态,只有在AOF持久化功能关闭的时候,才会使用RDB文件来还原数据库状态。

    接下来说一下,RDB自动保存,前面已经说了,RDB可以通过手动执行,SAVE命令和BGSAVE命令,也可以通过配置让服务器自动执行,那么如何配置呢?

    Redis.conf中可以配置,默认配置如下:

     save 900 1
    save 300 10
    save 60 10000

    以上表示的意思是,

    • 900秒之内对服务进行了至少一次修改
    • 300秒之内服务器进行了至少10次修改
    • 60秒之内对服务器进行了至少10000次修改。

    这些条件满足其中的任意一个bgsave命令就会自动执行。

    那么你可能会好奇,服务器是怎么知道我做了多少修改的?服务器中有个dirty计数器和一个lastsave时间戳

    当服务器执行一个数据库修改命令之后,dirty计数器就会进行更新,命令修改了多少次数据库,dirty就会增加多少,如:【set msg  hello】修改了一个,那么dirty就加一,如果【mset msg word name nihao age 20】那么dirty就增加三

    lastsave属性记录上次服务器执行保存操作的时间,是一个unix时间戳,通过这两个属性,可以很简单的距离上次保存已经多少时间了,以及修改了多少次数据库,一旦满足以上三个条件,那么就自动调用bgsave命令,同时更新lastsave属性和dirty属性归零。

    至于检查保存条件是否满足这个工作,是由Redis服务器周期性操作函数serverCron默认间隔100毫秒执行一次检查,这个函数有很多地方用到,注意一下,这个函数是对正在运行的服务器进行维护的函数,在Redis事件中会有提到(Redis服务器是一个事件驱动程序,什么是事件驱动呢?就是发生事件的时候才会动一下,不然就跟死了一样,事件驱动又分为文件事件和时间事件,ServerCron就是一种时间驱动,至于文件驱动,其实就是客户端发过来一个命令,服务器才会去执行,然后给客户端返回结果)

    最后说一点,Redis本身自带了一个RDB文件检查工具redis-check-dump,可以使用这个工具对rdb文件是否完整进行检查

    【文章来源:http://www.linuxidc.com/Linux/2015-07/120733.htm】

  • 相关阅读:
    Median Value
    237. Delete Node in a Linked List
    206. Reverse Linked List
    160. Intersection of Two Linked Lists
    83. Remove Duplicates from Sorted List
    21. Merge Two Sorted Lists
    477. Total Hamming Distance
    421. Maximum XOR of Two Numbers in an Array
    397. Integer Replacement
    318. Maximum Product of Word Lengths
  • 原文地址:https://www.cnblogs.com/wolfshining/p/7833205.html
Copyright © 2011-2022 走看看