Redis RDB 持久化 实现原理


1. RDB 概念

官方解析

By default Redis saves snapshots of the dataset on disk, in a binary file called dump.rdb. You can configure Redis to have it save the dataset every N seconds if there are at least M changes in the dataset, or you can manually call the SAVE or BGSAVE commands.

本人解析

将内存中数据,以镜像的方式存储到 dump.rdb 二进制文件中

通过配置 N 秒刷了多少条数据进行触发

也可以通过 SAVE 或者 BGSAVE 命令进行触发

2. RDB 配置

save 900 1      #900 秒内如果至少有 1 个 key 的值变化,则保存

save 300 10    #300 秒内如果至少有 10 个 key 的值变化,则保存

save 60 10000  #60 秒内如果至少有 10000 个 key 的值变化,则保存

stop-writes-on-bgsave-error yes 

#当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据

rdbcompression yes  #是否进行压缩存储

rdbchecksum yes  #使用CRC64算法来进行数据校验

dbfilename dump.rdb #快照的文件名

dir ./  #快照文件的存放路径

3. 定时检查是否刷开子进程刷盘

1). 每次写命令执行的时候 变量 server.dirty ++

2). 默认情况下每100ms 触发一次定时器,检查是否满足配置条件

save 900 1

#900 秒内如果至少有 1 个 key 的值变化,则保存 save 300 10

#300 秒内如果至少有 10 个 key 的值变化,则保存 save 60 10000

#60 秒内如果至少有 10000 个 key 的值变化,则保存

3). 开启一个子进程将数据镜像刷到磁盘

开启的子进程是采用 copy on write 的技术, 在有写命令的时候,才会复制2份

4. RDB 刷盘过程

1). 创建一个 tmp-$pid.rdb 的临时文件

2). 按 RDB 存储协议 追加数据到 tmp-$pid.rdb 文件中

RDB 文件 最开头 5 个字节 是存储的是 REDIS 5个字母

再接下来的5个字节是RDB版本号,例如:0006

接着就按 Redis 数据库顺序根据不同 存储的类型刷数据了

不过什么类型,过期时间在前面,然后是就是数据类型,再接着就是key值,和 val值

当所有 db 都遍历完之后,接着写一下 255 这个数字,占1个字节

最后刷一个 cksum 值

3). 当所有数据追加到 tmp-$pid.rdb 完之后,对句柄进行close

4). 将 tmp-$pid.rdb 文件重命名为 dump.rdb

这里为什么要先写一个 tmp临时文件,写完之后再修改 dump.rdb 文件呢?

假如直接写 dump.rdb文件,假如中途写失败了呢?那文件不就损坏了么?!

5. RDB 刷盘失败

什么时候会刷盘失败?

A. 当上一次rdb刷盘还没有完成的时候,不会再开新的子进程刷盘 B. 开启子进程失败,子进程被kill 或者运行过程 异常退出

不管什么原因造成子进程退出 ,在子进程结束回调的时候都会修改server.lastbgsave_status=REDIS_ERR

6. stop-writes-on-bgsave-error

在 开启了 stop-writes-on-bgsave-error yes

并且 上一次 RDB 刷盘之无,刷盘失败了,则会阻塞 写和PING 等命令

/* Don't accept write commands if there are problems persisting on disk

    * and if this is a master instance. */

    if (((server.stop_writes_on_bgsave_err &&

          server.saveparamslen > 0 &&

          server.lastbgsave_status == REDIS_ERR) ||

          server.aof_last_write_status == REDIS_ERR) &&

        server.masterhost == NULL &&

        (c->cmd->flags & REDIS_CMD_WRITE ||

        c->cmd->proc == pingCommand))

    {

        flagTransaction(c);

        if (server.aof_last_write_status == REDIS_OK)

            addReply(c, shared.bgsaveerr);

        else

            addReplySds(c,

                sdscatprintf(sdsempty(),

                "-MISCONF Errors writing to the AOF file: %s\r\n",

                strerror(server.aof_last_write_errno)));

        return REDIS_OK;

    }

7. 手动触发 RDB 镜像生成

7.1 SAVE 命令

void saveCommand(redisClient *c) {

    if (server.rdb_child_pid != -1) {

        addReplyError(c,"Background save already in progress");

        return;

    }

    if (rdbSave(server.rdb_filename) == REDIS_OK) {

        addReply(c,shared.ok);

    } else {

        addReply(c,shared.err);

    }

}

SAVE 命令,是阻塞式的

是由当前主线程进行刷盘,而不是开子进程刷盘

刷完之后再返回给客户端

7.2 BIGSAVE 命令

void bgsaveCommand(redisClient *c) {

    if (server.rdb_child_pid != -1) {

        addReplyError(c,"Background save already in progress");

    } else if (server.aof_child_pid != -1) {

        addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress");

    } else if (rdbSaveBackground(server.rdb_filename) == REDIS_OK) {

        addReplyStatus(c,"Background saving started");

    } else {

        addReply(c,shared.err);

    }

}

BIGSAVE 命令,是立马开启一下子进程,后台进行刷盘

立马返回信息给你客户端

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343