Benjamin

静以修身,俭以养德,非澹薄无以明志,非宁静无以致远。
随笔 - 397, 文章 - 0, 评论 - 196, 引用 - 0
数据加载中……

Redis持久化之RDB

一、Redis持久化原因:Redis是内存数据库,数据都是存放到内存中的,如突然宕机,数据就会丢失,因此必须有一种机制来保证redis在内存中的数据不会                                    丢失,这种机制就叫redis持久化机制。
二、支持的持久化有如下几种:
  1. RDB(Redis 数据库):RDB 持久性以指定的时间间隔执行数据集的时间点快照(某一时刻的状态到磁盘以文件的形式进行全量备份)。

  2. AOF(仅追加文件):AOF 持久性记录服务器接收到的每个写操作。然后可以在服务器启动时再次重播这些操作,从而重建原始数据集。命令使用与 Redis 协议本身相同的格式进行记录。

  3. RDB + AOF:还可在同一个实例中组合 AOF 和 RDB

三、RDB是Redis DataBase 的缩写,中文名为快照/内存快照,RDB持久化是把当前进程数据生成快照保存到磁盘上的过程,由于是某一时刻的快照,那么快照中的值要早于或者等于内存中的值。
1、默认情况下,Redis 将数据集的快照保存在磁盘上名为 dump.rdb 的二进制文件中。
2、Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave。一般使用bgsave,既能提供数据的可靠性,也能避免影响redis性能。
save:在主线程中执行,会导致阻塞;
bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置。
伪代码
void SAVE(){
    # 创建RDB文件
    rdbSave();
}

void BGSAVE(){
    # 创建子进程
    pid = fork();

    if (pid==0){
        
        # 子进程创建RDB
        rdbSave();

        # 创建完成之后向父进程发送信息
        signal_parent();
        
    }else if (pid>0){
        
        # 父进程(主线程)继续处理客户端请求,并通过轮询等待子进程的返回信号
        handle_request_and_wait_signal();
        
    }else{
        
        # 处理异常
        ...
    }
}

3、redis.conf中配置RDB:内存快照虽然可以通过命令来进行,但生产环境下多数情况都会设置其周期性执行条件,自动保存。
# 周期性执行条件的设置格式为
save <seconds> <changes>

# 默认的设置为:save 900 1save 300 10save 60 10000
# 以下设置方式为关闭RDB快照功能save ""
以上三项默认信息设置代表的意义是:
如果900秒内有1条Key信息发生变化,则进行快照;
如果300秒内有10条Key信息发生变化,则进行快照;
如果60秒内有10000条Key信息发生变化,则进行快照。

savaparams属性
struct redisServer{
    ...
       // 修改次数的计数器
    long dirty;

    // 上一次成功执行RDB快照的时间
    time_t lastsave;

    // 保存条件配置的数组
    struct saveparam *saveparams;

    ...
}

struct saveparam{

    // 秒数
    time_t seconds;

    // 修改次数
    int changes;
}
②周期性检查保存条件:serverCron函数默认每隔100毫秒就会执行一次,该函数的其中一个作用就是检查save命令设置的保存条件是否被满足,是则执行BGSAVE命令。伪代码如下

    void serverCron(){
    ...
    for (saveparam in server.saveparams){
        // 计算距离上次成功进行RDB快照多少时间
        save_interval = unixtime_now() - server.lastsave;
        // 如果距离上次快照时间超过条件设置时间 && 数据库修改次数超过条件所设置的次数,则执行快照操作
        if (save_interval > saveparam.seconds && server.dirty >= saveparam.changes){
            BGSAVE()
        }
    }
    ...
}

4、
Copy-On-Write, COW
 redis在执行bgsave生成快照的期间,将内存中的数据同步到硬盘的过程可能就会持续比较长的时间,而实际情况是这段时间Redis服务一般都会收到数据写操作请求。这时Redis 就会借助操作系统提供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作。
bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。
     如果主线程对这些数据也都是读操作,那么,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一块数据,那么,这块数据就会被复制一份,生成该数据的副本。然后,主线程在这个数据副本上进行修改。同时,bgsave 子进程可以继续把原来的数据写入 RDB 文件。
· 写时复制机制保证快照期间数据可修改,既保证了快照的完整性,也允许主线程同时对数据进行修改,避免了对正常业务的影响。
5、
快照的频率快照间隔越短,宕机时丢失数据越少。但频率越高,对磁盘会造成压力,另外也会频繁阻塞主线程。这个根据业务和实际来确定。
6、
优点
RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景;
Redis加载RDB文件恢复数据要远远快于AOF方式;
7、
缺点:实时性不够,无法做到妙计持久化;
              每次调用bgsave都需要fork子进程,占用系统资源;
              RDB文件是二进制的,没有可读性

posted on 2024-07-15 14:45 Benjamin 阅读(34) 评论(0)  编辑 收藏 引用 所属分类: 数据库


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理