专栏首页程序员小灰你管这破玩意叫 RDB ?

你管这破玩意叫 RDB ?

我是个 redis 服务,我马上就要挂了

我已经运行了好几年了,我的内存中存储着好多键值对。

如果我挂了,那样我内存中的数据就全没了。

我得想个办法,时不时把数据复制到硬盘上保存起来。

我把这个伟大的计划,称为持久化计划

停下手头的工作

我首先想到的最简单的办法,就是先拒绝新来的命令,开始将内存中的数据复制到硬盘。

等拷贝完成后,再开始接受新命令。

这样可以保证我拷贝的时候,没有新来的命令修改内存,也即保证了时点性

简单说就是,我保存的是某一时刻的 Redis 内存状态。

但这样每次持久化都要阻塞客户端命令,肯定要被骂。

不停止手头的工作

这好办,那我就不停止手头的工作呗,一边接受命令,一边做持久化,如下。

这样效率提高了不少,持久化不再阻塞客户端执行命令了。

但是,你有没有注意到,内存中,某一时刻的数据,只有三种情况:

闪客 18 低并发编程

低兄 18 低并发编程

低兄 18 求三连

而此时硬盘中持久化的数据是:

闪客 18 求三连

它无法表示任何一个时刻的内存数据。

那这样的快照就失去了意义,也即没有保证时点性。

这显然也是不行的。

先复制一份内存

这可咋办呢?

停止手头的工作可以保证时点性,但阻塞了客户端。

不停止手头的工作,虽然不阻塞客户端,但又无法保证时点性。

真令人头大啊。

抓了一会头皮后,我冷静了下来,开始分析。

时点性是必须保证的,否则快照就没有了意义,那就只能尝试将阻塞客户端的时间变短一点了

之前的阻塞客户端时间,是消耗在持久化,也就是内存拷贝到硬盘这个过程。

优化一下,先从内存中拷贝一份到另一块内存空间,然后再对这块新的内存空间进行持久化。

这样,持久化的过程不耽误客户端命令,同时不受客户端命令影响,保证了时点性。

而阻塞客户端的时间,仅仅是内存与内存之间拷贝一份数据的时间,相比于整个持久化过程,可以忽略不计。

完美!

带着这套完美的方案,我去找我的主人邀功了。

写时复制

我:主人,我做好持久化方案啦!

主人:嗯我看看... 哎呀,把内存复制一份,这个想法很好,但是差了点火候呀,你对操作系统了解的还不够深入。

我:啊,为啥呢?

主人:你想想看,你现在的目的,就是为了让持久化和处理客户端命令的这两个过程所用到的内存空间隔离开,是不是?

我:嗯嗯是的。

主人:对呀,那其实你只需要新建一个进程去做持久化的过程即可,不同进程之间的内存是隔离的,也就是新建一个进程,会将原有进程的内存空间完全拷贝一份新的。

我:啊,那这不是和我自己复制一份内存一样嘛,耗时差不多吧?

主人:我刚刚的图只是给用户的感觉是这样的,实际上,linux 采用了写时复制技术,在 fork 出子进程时并没有立刻将内存进行拷贝,仅仅是拷贝了一份映射关系,让它们暂时指向同一个内存空间。

主人:而当父子进程对这块内存空间进行写操作时,才会真正复制内存,而且是以页为单位。

我:原来如此,也就是说,我可以利用操作系统的进程的写时复制内存的原理,来代替我自己复制全部内存这个方案,因为持久化过程,对内存的写操作想来也不会特别多,大多数值都是不变的,所以这样就提高了效率。

主人:是的,正是如此。

我:妙呀!

我赶紧把方案修改了,要持久化时我就 fork 一个子进程去做这件事,由操作系统的进程内存隔离的特征替我保证时点性,写时复制原理替我保证效率,也就是减少客户端阻塞时间,伪代码大概是这个样子。

void rdbSaveBackground() {
    // 子进程处理(利用了操作系统的写时复制技术)
    if ((childpid = fork()) == 0) {
        // 落盘主方法
        rdbSave();
    }
}

完美!

还没定结构呢

刚刚光顾着想持久化的过程了,还没定写到磁盘中的数据格式呢。

那就定一个呗。

假如我的 Redis 内存只有一条数据,是通过下面的命令写入的:

set dibingfa niubi

那持久化后落到磁盘中的 rdb 文件将会是这个样子。

好了,大功告成,我再也不用担心自己挂了,会有人帮我从持久化文件中恢复我的内存数据的。

但没来得及持久化的,我就不管了。

具体什么时候进行一次持久化,我给主人留了一个配置

save m n

表示 m 秒内数据集存在 n 次修改时,自动触发一次持久化。

主人也可以配置多个这样的配置项。

而我也好心给主人配了个默认的配置项,并写了段注释。

# Save the DB on disk:
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
save 900 1
save 300 10
save 60 10000

我想以主人的英文水平,应该可以读得懂。

好啦,这回真的是大功告成了!

这个破玩意,我给起个名字,就叫 RDB

没什么特别的含义,其实就是用我的名字作为开头,Redis DB 而已。

本文分享自微信公众号 - 程序员小灰(chengxuyuanxiaohui)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-05-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 你管这破玩意叫 class?

    我是一个 .java 文件,名叫 FlashObject.java,叫我小渣就行。

    小灰
  • 你管这破玩意叫 OAuth2?

    这几秒钟之内发生的事情,在外行的用户视角看来,就是在豆瓣官网上输了个 qq 号和密码就登录成功了。

    macrozheng
  • 你管这破玩意叫哨兵?

    老板:现在有四个 Redis 节点摆在你面前,一主三从,你负责盯着点,主节点挂了你赶紧想办法拿从节点顶上来,交给你了!

    Java识堂
  • 你管这破玩意儿叫 Token?

    上周我们在团队内部首次采用了 jwt(Json Web Token) token 这种 no-session 的方式来作用户的账号验证,发现网上很多文章对 to...

    macrozheng
  • 科普 | 你管这破玩意儿叫TCP?

    经过《如果让你来设计网络》这篇文章中的一番折腾,只要你知道另一位伙伴 B 的 IP 地址,且你们之间的网络是通的,无论多远,你都可以将一个数据包发送给你的伙伴 ...

    CloudBest
  • 你管这破玩意叫“对撞指针”?

    本文由一道 leetcode 简单题,引出在刷题和笔试经常用到的双指针中的“对撞指针”解题技巧,供大家参考,希望能对大家有所帮助。

    程序员小熊
  • 你管这破玩意儿叫负载均衡?

    相信大家都听过这样的一道经典面试题:「请说出在淘宝网输入一个关键词到最终展示网页的整个流程,越详细越好」

    kunge
  • 好家伙,你管这破玩意叫“双指针”?

    给出一个数组,在数组中找到两个数,使得它们的和最接近目标值但不超过目标值,返回它们的和。

    程序员小熊
  • 好家伙,你管这破玩意叫“双指针”?

    给出一个数组,在数组中找到两个数,使得它们的和最接近目标值但不超过目标值,返回它们的和。

    程序员小熊
  • 你管这玩意叫双系统?直接在 Windows 上体验 Linux

    原来是 Windows官方的Linux子系统 (WSL),终于支持Linux GUI了!

    刘盼
  • 《吊打面试官》系列-Redis基础

    Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难。作为一个在互联网公司面一次拿一...

    Rude3Knife的公众号
  • 《吊打面试官》系列-Redis基础

    Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难。作为一个在互联网公司面一次拿一...

    Java3y
  • 你管这叫"线程安全"?

    1.什么叫线程安全?2.线程安全与变量的关系?•变量又与堆/栈/静态存储区有密切关系

    小码甲
  • 《吊打面试官》系列-Redis基础

    Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难。作为一个在互联网公司面一次拿一...

    jeanron100
  • 如何选择数据库

    一层一层铺开,一对多,这是「层次模型数据库」(Hierarchical Database)。

    Java3y
  • 低并发编程

    大家好,我是闪客,感谢 高性能服务器开发 提供的平台让我在这里给大家介绍自己,这是我的公众号卡片。

    范蠡
  • Redis 这破玩意为什么那么快?

    shell 程序把我的程序加载到了内存,开始执行我的 main 方法,一切就从这里开始了。

    macrozheng
  • 现在去搜索这个,你会来感谢我的!

    说实话,技术公众号现在竞争真挺大的,用遍地都是形容也毫不为过,这不,号一多就容易变得“内卷”起来。

    轩辕之风
  • 神奇的闪电缓存,带系统飞

    缓存,在高并发的应用中,用的那是相当多。为什么?就因为I/O实在是慢!为了解决不同组件之间的速度差,大家都寄希望于加入一个中间层,期待产生一些魔幻的事。

    xjjdog

扫码关注云+社区

领取腾讯云代金券