Redis Source Code Read Log( 13 rdb)

Part 1: rdb 三种方式

1. save  block main process

2. bgsave [schedule]  fork rdb child process

3. background save by config  fork rdb child process

# save “”

save 900 1             > 1 keys after 900sec / 15min

save 300 10           > 10 keys after 300sec / 5min

save 60 10000       > 10000 keys after 60sec / 1min

Part 2: core API rdbSave

rdb 的核心操作 API,时序流程如下

注意,fflush 以及 fsync 操作,因为 子进程采用的退出方式是 _exit() 调用,而非 exit。

这两个 exit 的区别是 exit() 调用会冲刷 ISO C I/O 缓冲buffer,但是,_exit() 不会,所以才会手动 fflush & fsync 在 _exit() 清空缓冲中的残留数据,保证 data written on dick。

Part 3: Flows

save command

rdb 子进程不存在,即数据库此时没有正在处理 background rdb save task,此时,会正常响应 save 命令:

callback saveCommand

directly call rdbSave & block main process up to save being done.

bgsave [schedule]

rdb 子进程存在,此时直接返回错误,而并不查看 schedule 选项。

aof 子进程存在,此时将记录 schedule 要求选项, scheduled 状态记为 1,后续继续处理

处理方式: 当 rdb 或者 aof 子进程均不存在,schedule 状态为1时,serverCron 轮询任务中,会直接调用 rdbSaveBackground ,后将 schedule 状态置为0,后续处理逻辑与下面类似。

rdb aof 子进程均不存在,忽略 schedule 选项,将直接处理 bgsave 命令,处理逻辑如下:

定时触发的 rdb

当无子进程时,serverCron 轮询任务中,会进行 config save 条件的检查。

下图所示,便是 save 中条件在 redis 代码中的存储表达方式。

server key 计数器 dirty changes 进行比较的同时, 进行当前时间与last_save差值 与 seconds 的比较,同时满足时,触发 bgsave 操作。

注意:

每次 save/bgsave操作,都会更新对应的 dirty (主要的善后操作)

save: save 成功之后 dirty 值会直接被置 0,因为 save 是 阻塞式的全量dbdump操作。

bgsave & timed bgsave 中,main bgsave之前记录 dirty_before_save (即当前dirty),然后子进程正常退出之后,server端更新 dirty 值为 dirty -= dirty_before_save

Part 4: rdb 中途有失败情况怎么办?

失败状态记录,默认为 OK

lastbgsave_status

save 命令

第一,忽略该值,无脑 rdb

第二,save 一旦成功,会重置该值为 OK 状态

bgsave 命令

第一,非 schedule rdb 任务,如果满足触发条件,那么无脑 rdb

,一旦成功,会重置该值为 OK 状态

timed rdb bgsave & schedule bgsave

短期(如下定义,5秒钟),无法继续进行 bgsave 操作,之后,继续无脑进行对应的 rdb 检查或操作

#define CONFIG_BGSAVE_RETRY_DELAY 5 /* Wait a few secs before trying again. */

Part 5: PIPE 介绍 以及 redis rdb 子进程退出状态管理

pipe 介绍

Linux 匿名管道,一般用于父子进程间进行“共享式”通讯。

可采用 int pipe(int fd[2]); 进行创建:其中 fd[0] 只读, fd[1] 只写。父子进程将 fd 以“文件共享”方式继承下来,任何一个写端写,写入的都是到内核 pipe 的同一个共享区域,任何一个读端都可以读出其中内容。

端进行读的时候,除非结合其中的数据进行判断,否则,无法获知其中的数据是哪一个写端写入的。

所以,一般的,写进程不读,而读进程不写,以达到有序通讯的目的。

redis 中,只有 child 进程进行写,而 main 进程进行读。

pipe 作为一种 fd, socket 一样,可以用 epoll 进行读写的触发。

redis rdb 子进程退出状态处理

rdb 进程退出状态处理

1. 为什么要处理子进程退出状态处理?

防止子进程成为僵尸进程。同时查看子进程退出状态,进行一些后处理的操作。

2. 怎么处理的?

第一:在 serverCron 轮询任务中,非阻塞方式周期性调用 wait 查看子进程是否退出

第二:在 确认子进程退出后,read 父子进程通讯管道中的数据。

第三:rdb 持久化策略,只是简单记录 管道中 回传的值,无其他作用。

rdb 父子进程的通讯消息类型:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值