Redis的快照为什么不会阻塞其他请求?
副问题[/!--empirenews.page--]
为什么这么计划(Why's THE Design)是一系列关于计较机规模中措施计划决定的文章,我们在这个系列的每一篇文章中城市提出一个详细的题目并从差异的角度接头这种计划的优弱点、对详细实现造成的影响。假如你有想要相识的题目,可以在文章下面留言。 固然我们常常将 Redis 看做一个纯内存的键值存储体系,可是我们也会用到它的耐久化成果,RDB 和 AOF 就是 Redis 为我们提供的两种耐久化器材,个中 RDB 就是 Redis 的数据快照,我们在这篇文章想要说明 Redis 为什么在对数据举办快照耐久化时会必要行使子历程,而不是将内存中的数据布局直接导出到磁盘长举办存储。 概述 在详细说明本日的题目之前,我们起首必要相识 Redis 的耐久化存储机制 RDB 毕竟是什么,RDB 会每隔一段时刻中对 Redis 处事中当下的数据集举办快照,除了 Redis 的设置文件可以对快照的隔断举办配置之外,Redis 客户端还同时提供两个呼吁来天生 RDB 存储文件,也就是 SAVE 和 BGSAVE,通过呼吁的名字我们就能猜出这两个呼吁的区别。 个中 SAVE 呼吁在执行时会直接阻塞当前的线程,因为 Redis 是 单线程 的,以是 SAVE 呼吁会直接阻塞来自客户端的全部其他哀求,这在许多时辰对付必要提供较强可用性担保的 Redis 处事都是无法接管的。 我们每每必要 BGSAVE 呼吁在靠山天生 Redis 所稀有据对应的 RDB 文件,当我们行使 BGSAVE 呼吁时,Redis 会立即 fork 出一个子历程,子历程会执行『将内存中的数据以 RDB 名目生涯到磁盘中』这一进程,而 Redis 处事在 BGSAVE 事变时代如故可以处理赏罚来自客户端的哀求。 rdbSaveBackground 就是用来处理赏罚在靠山将数据生涯到磁盘上的函数: int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) { pid_t childpid; if (hasActiveChildProcess()) return C_ERR; ... if ((childpid = redisFork()) == 0) { int retval; /* Child */ redisSetProcTitle("redis-rdb-bgsave"); retval = rdbSave(filename,rsi); if (retval == C_OK) { sendChildCOWInfo(CHILD_INFO_TYPE_RDB, "RDB"); } exitFromChild((retval == C_OK) ? 0 : 1); } else { /* Parent */ ... } ... } Redis 处事器会在触发 BGSAVE 时挪用 redisFork 函数来建设子历程并挪用 rdbSave 在子历程中对数据举办耐久化,我们在这里固然省略了函数中的一些内容,可是整体的布局还长短常清楚的,感乐趣的读者可以在点击上面的链接相识整个函数的实现。 行使 fork 的目标最终必然是为了不阻塞主历程来晋升 Redis 处事的可用性,可是到了这里我们着实可以或许发明两个题目: 为什么 fork 之后的子历程可以或许获取父历程内存中的数据? fork 函数是否会带来特另外机能开销,这些开销我们怎么样才可以停止? 既然 Redis 选择行使了 fork 的方法来办理快照耐久化的题目,那就声名这两个题目已经有了谜底,起首 fork 之后的子历程是可以获取父历程内存中的数据的,而 fork 带来的特殊机能开销对比阻塞主线程也必然是可以接管的,只有同时具备这两点,Redis 最终才会选择这样的方案。 计划 为了说明上一节提出的两个题目,我们在这里必要相识以下的这些内容,这些内容是 Redis 处事器行使 fork 函数的条件前提,也是最终促使它选择这种实现方法的要害: 通过 fork 天生的父子历程会共享包罗内存空间在内的资源; fork 函数并不会带来明明的机能开销,尤其是对内存举办大量的拷贝,它能通过写时拷贝将拷贝内存这一事变推迟到真正必要的时辰; 子历程 在计较机编程规模,尤其是 Unix 和类 Unix 体系中,fork 都是一个历程用于建设本身拷贝的操纵,它每每都是被操纵体系内核实现的体系挪用,也是操纵体系在 *nix 体系中建设新历程的首要要领。 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |