• Redis(五)——持久化机制


    Redis是内存数据库,需要将存储在内存中的数据库状态保存到磁盘里,避免数据丢失。持久化即把数据保存到可永久存储的设备中。

    一、RDB持久化机制

    RDB文件是数据库 某个状态经过压缩后的二进制文件,通过该文件还原到数据库当初的状态。默认情况下,Redis的RDB文件名为dump.rdb。

    1.RDB文件的创建和载入

    (1)通过savebgsave命令创建RDB文件

    • save命令会阻塞Redis服务器进程,知道RDB文件创建完毕,阻塞期间不可以处理任何请求指令。(不消耗内存但阻塞)
    • bgsave命令会派生出一个子进程fork,让子进程去创建RDB文件,相当于子进程执行save命令,自己(父进程)继续执行请求指令。在bgsave期间,父进程会拒绝save和bgsave指令,防止产生竞争条件;对于BGREWRITEAOF指令也会延迟到bgsave后执行,该指令虽然是由子进程执行,没有冲突,但从性能方面考虑,不能同时执行。(消耗内存但不阻塞)

    (2)服务器启动时自动载入RDB文件

    2.自动间隔性保存

    在redis.window.conf配置文件中,有这么三行代码

    save 900 1  
    save 300 10
    save 60 10000

    服务器在900s内,对数据库进行了至少1次修改

    服务器在300s内,对数据库进行了至少10次修改

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

    只要满足任意一个条件,bgsave命令就会自动执行.

    服务器状态的结构体 包含了 保存条件结构体,可以自行设置保存条件

    //服务状态
    struct
    redisServer{ //.. struct saveparam* saveparam;//记录保存条件的数组 //.. };
    //保存条件
    struct saveparam{ time_t seconds;//秒数 int changes;//修改数 };

    服务器状态还有2个属性来判断是否执行保存

    //服务器状态
    struct redisServer{
        //..
        struct saveparam* saveparam;//记录保存条件的数组
        long long dirty;//修改计数器,记录上一次修改后,数据库改了多少次
        time_t lastsave;//上一次执行保存的时间戳
        //..
    };

    3.RDB文件结构

    • REDIS部分的长度为5字节,保存"REDIS"五个字符,通过这五个字符快速检查所载入的文件是不是RDB文件,这里不是C字符串"REDIS"。
    • db_version长度为4字节,它的值是一个字符串表示的整数,例如"0006"就代表RDB文件的版本为第六版。
    • databases部分包含零个或任意多个数据库,以及各个数据库中的键值对数据。如果服务器的数据库状态为空,则database为空;状态不为空也根据数据库所保存的键值对信息而长度不同。
    • EOF(End of File)表示读入程序读到文件尾,占1字节。
    • check_sum是一个8字节长的无符号整数,保存一个校验和,这个校验和是程序通过前四个部分计算得出的。载入文件时会将载入数据所计算出的结果和原本记录的check_sum进行对比,以此来检查RDB文件是否有误。

    databases部分可以保存任意多个非空数据库

    • SELECTDB常量的长度为1字节,当读入时就知道下一个是数据库号码。
    • db_number保存着一个数据库号码,长度可以是1、2、5字节。读到这个东西会调用select命令,根据读入的号码切换。
    • key_value_pairs部分保存了数据库中所有键值对信息,过期的键没删除的话也在里面,每个键值对信息如下,如果不带过期时间则没有前面两个信息根据TYPE类型来选择保存的value对象类型

    二、AOF持久化机制

    AOF全称是Append Only File,通过保存Redis服务器所执行的写命令来记录数据库状态。是日志文件,通过执行命令还原数据库状态。被写入AOF文件的所有命令都是以Redis命令请求协议格式(纯文本)保存的,

    1.AOF持久化的实现

    • 命令追加:服务器执行完一个写命令之后会把该命令追加到aof_buf缓冲区的末尾
    • 写入与同步:redis服务器进程是一个事件循环,负责接收客户端的命令请求并回复。时间事件负责执行像serverCron函数这样需要定时运行的函数。服务器每次结束一个事件循环之前,都会调用flushAppendOnlyFile函数,考虑是否需要将aof_buf缓冲区中的内容写入和保存到AOF文件里

    很显然,always效率最慢,安全性最高,即使出现故障最多也只是丢失一个事件循环中的命令数据;第二个折中;第三个写入AOF文件很快,不同步会导致数据累积,下一次同步时耗时最长。

    2.AOF文件的载入和数据还原

    服务器只要读入并重新执行一遍AOF文件里的命令就可以还原数据库状态

    3.AOF重写

    如果堆积很多命令造成文件庞大,不如保留键最后的值,将若干条命令替换成一条(设置键值)。

    4.AOF后台重写

    为了防止阻塞,服务器将AOF重写交给子进程进行,父进程继续执行客户端请求的命令。在AOF重写期间执行其他写命令的话会使得重写后的AOF文件不能还原到最新状态。因此在AOF重写期间,父进程将此期间执行的写命令,除了追加进AOF缓冲区,顺便追加进AOF重写缓冲区,待重写完成,把AOF重写缓冲区的内容追加到新的AOF文件,这就保证了状态一致。

    三、对比分析

    还是老样子,有利必有弊,一般都是结合使用。


     参考&引用

    《redis设计与实现》

  • 相关阅读:
    android studio中timber的配置
    bufferknife框架的正确使用方式 -终于他么知道了
    开源的图像滤镜库----for Android
    HSV做通道分离是出现的Vector内存越界错误
    HSV与RGB的相互转换的公式
    Windows下python的第三方库的安装
    Python出现"Non-ASCII character 'xe6' in file"错误解决方法
    Verilog的IDE Quartus II
    Java-ZipUtil工具类
    Java-JDBCUtil工具类
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/13538255.html
Copyright © 2020-2023  润新知