Redis数据持久化

12 篇文章 4 订阅

        由于Redis是内存数据库,一旦服务器进程退出,服务器中的数据库状态也会消失。为解决这个问题,Redis提供了RDB快照形式、AOF日志形式两种持久化方式,将内存中的数据保存到磁盘中,以免数据意外丢失。

一、RDB持久化

        RDB持久化就是将服务器某个时间点上的数据库状态以快照形式保存到一个二进制文件中,在Redis服务器重新启动时可以自动载入RDB文件,还原数据库状态。有两个Redis命令可以用于生成RDB文件:

(1)save:阻塞Redis服务器进程不能提供任何命令请求,直到RDB文件创建完成为止;

(2)bgsave:派生子进程创建RDB文件,父进程继续处理命令请求;

在rdb.c/rdbSave和rdb.c/rdbSaveBackground两个函数中实现,其思想如下:

# Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success 
# 将数据库保存到磁盘上。
# 保存成功返回 REDIS_OK ,出错/失败返回 REDIS_ERR 。
# SAVE
def save():
    # 创建RDB文件
    rdbSave()

# BGASVE
def bgsave():
    # 创建子进程
    pid = fork()
    if pid == 0:
        # 子进程负责创建RDB文件
        rdbSave()
        # 完成后向父进程发送信号
        signal_parent()
    elif pid>0:
        # 父进程继续处理命令请求,并轮询等待子进程的信号
        handle_request_and_wait_signal()
    else:
        # 处理出错的情况
        handle_fork_error()

        由上可知,bgsave命令可以在不阻塞服务器进程的情况下执行,因此可以设置服务器的备份时间,让服务器每隔一定时间自动执行一次bgsave命令,如下设置保存条件:

save 300 10   //300S内对数据库进行了至少10次修改,BGSAVE就会被执行

        在Redis服务器中有三个属性与此有关:saveparam结构、dirty、lastsave

struct redisServer{
    //...
    //记录了保存条件的数组
    struct saveparam *saveparams;
    //修改计数器,距离上一次成功备份又对数据库状态进行了修改的次数
    long long dirty;
    //上一次执行备份的时间戳
    time_t lastsave;
    //...
}
struct saveparam{//保存条件save 300 10
    //秒数
    time_t seconds;
    //修改次数
    int changes;
}

        Redis服务器周期性操作函数serverCron函数默认每100毫秒执行一次,它其中一项任务就是检查save选项所设置的保存条件是否已经满足,如果满足则执行bgsave命令。其思想如下:

def serverCron():
    # ...
    # 遍历保存条件
    for saveparam in server.saveparams:
        # 计算距离上次执行备份操作有多少秒
        save_interval = unixtime_now() - sever.lastsave
        # 如果数据库状态的修改次数超过条件所设置的次数,并且距离上次保存的时间超过设置时间
        # 执行保存操作
        if server.dirty >= saveparam.changes and save_interval > saveparam.seconds:
            bgsave()
    # ...


二、AOF持久化

        AOF持久化则通过保存Redis服务器所执行的所有的写命令来记录数据库状态。被写入AOF文件的所有命令都是以Redis的命令请求协议格式保存的,Redis的命令请求协议是纯文本格式。AOF持久化的方式如下所示:


AOF持久化功能的实现分三步进行:

(1)命令追加(append):服务器执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区末尾。

(2)文件写入:服务器在一个事件循环结束之前,调用flushAppendOnlyFile函数将aof_buf缓冲区中的内容写入和保存到AOF文件中。

(3)文件同步(sync):根据服务器配置的appendfsync选项的值来决定文件的同步操作。

appendonly yes //启用AOF持久化方式,默认是everysec
appendfsync always //每个事件循环都要将aof_buf缓冲区中内容写入AOF文件,并同步到AOF文件。最慢但最安全
appendfsync everysec //每个事件循环都要将aof_buf缓冲区中内容写入AOF文件,每秒在子线程中执行AOF文件同步。在性能和持久化方面做了折中
appendfsync no //每个事件循环都要将aof_buf缓冲区中内容写入AOF文件,AOF文件的同步由操作系统控制。性能最好,但持久化没保障


三、RDB持久化与AOF持久化比较        

        RDB持久化:保存了Redis在某时间点上的数据集,文件紧凑。但如果需要尽量避免在服务器故障时丢失数据,那么RDB不合适。

        AOF持久化:通过保存命令的形式保存数据库状态,同时可以设置保存的频率。针对相同数据集,AOF文件的体积大于RDB文件的体积,Redis引入了AOF重写机制以解决AOF文件体积膨胀问题。

        AOF重写机制的原理:首先从数据库中读取键现在的值,然后用一条写命令代替之前的多条写命令记录键值对,从而代替之前的多条命令。AOF重写的步骤:

(1)创建子进程开始新AOF文件重写;
(2)创建AOF重写缓冲区,记录创建子进程后Redis又执行的写命令;
(3)将重写缓冲区内容写到新AOF文件中,最后新AOF文件覆盖原AOF文件;

为什么要将AOF重写放到子进程中?

(a)Redis采用单线程处理命令请求,在子进程进行AOF重写期间,父进程可以继续处理命令请求;

(b)子进程带有服务器进程的数据副本,使用子进程而不是子线程是可以在避免使用锁的情况下保证数据的安全性。


参考文献
1、http://www.redis.net.cn/tutorial/3506.html
2、《Redis设计与实现》第二版---黄健宏
3、https://github.com/xingzhexiaozhu/redis-3.0-annotated
4、http://www.yiibai.com/redis/redis_strings.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值