• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

redis源码阅读之持久化优化——管道

redis 海叔叔 4年前 (2021-08-30) 37次浏览 已收录 0个评论

redis在进行持久化(aof或者rdb,这个以后会讲到,暂时理解是两种不同的方式将内存中的数据同步到磁盘)的时候,开始都是直接fork一个子进程出来,然后让这个子进程取进行持久化工作,在这期间,父进程照样工作,对外提供服务,接收到的命令也都缓存起来,子进程执行完任务之后,通知父进程,父进程收割,将缓存的命令同步到磁盘,最后OK。但是这样会出现一个问题,就是在子进程执行任务期间,如果父进程中缓存过多的数据就会造成性能下降,redis的大佬们就想出了利用管道来进行父子进程之间通信的方式来优化,就是子进程执行期间,将父进程接收到的命令通过管道来写给子进程,这样能够减少父进程收割完子进程之后,写入磁盘的数据的数目。
在redis当中简单的管道实现如下:

1. 打开:

void openChildInfoPipe(void) {
    if (pipe(server.child_info_pipe) == -1) {
        /* On error our two file descriptors should be still set to -1,
         * but we call anyway cloesChildInfoPipe() since can't hurt. */
        closeChildInfoPipe();
    } else if (anetNonBlock(NULL,server.child_info_pipe[0]) != ANET_OK) {
        closeChildInfoPipe();
    } else {
        memset(&server.child_info_data,0,sizeof(server.child_info_data));
    }
}

2. 关闭:

/* Close the pipes opened with openChildInfoPipe(). */
void closeChildInfoPipe(void) {
    if (server.child_info_pipe[0] != -1 ||
        server.child_info_pipe[1] != -1)
    {
        close(server.child_info_pipe[0]);
        close(server.child_info_pipe[1]);
        server.child_info_pipe[0] = -1;
        server.child_info_pipe[1] = -1;
    }
}

3. 发送数据给parent

/* Send COW data to parent. The child should call this function after populating
 * the corresponding fields it want to sent (according to the process type). */
void sendChildInfo(int ptype) {
    if (server.child_info_pipe[1] == -1) return;
    server.child_info_data.magic = CHILD_INFO_MAGIC;
    server.child_info_data.process_type = ptype;
    ssize_t wlen = sizeof(server.child_info_data);
    if (write(server.child_info_pipe[1],&server.child_info_data,wlen) != wlen) {
        /* Nothing to do on error, this will be detected by the other side. */
    }
}

4. 接收parent的数据

/* Receive COW data from parent. */
void receiveChildInfo(void) {
    if (server.child_info_pipe[0] == -1) return;
    ssize_t wlen = sizeof(server.child_info_data);
    if (read(server.child_info_pipe[0],&server.child_info_data,wlen) == wlen &&
        server.child_info_data.magic == CHILD_INFO_MAGIC)
    {
        if (server.child_info_data.process_type == CHILD_INFO_TYPE_RDB) {
            server.stat_rdb_cow_bytes = server.child_info_data.cow_size;
        } else if (server.child_info_data.process_type == CHILD_INFO_TYPE_AOF) {
            server.stat_aof_cow_bytes = server.child_info_data.cow_size;
        }
    }
}

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:redis源码阅读之持久化优化——管道
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址