由于函数默认返回C_OK
, 我们只需要看哪几类情况返回的不是C_OK
, 即C_ERR
,数据就不会被写入到客户端的 output buffer 中 。返回C_ERR
的情况:
- 客户端是个 fake client(用于加载 AOF 文件)
- 客户端是一个 master
- slave 的状态为 SLAVE_STATE_ONLINE 且其回调函数失败((c->replstate == SLAVE_STATE_ONLINE && !c->repl_put_online_on_ack)),或slave 的状态为 REPL_STATE_NONE
If the client should not receive new data, because it is a fake client (used to load AOF in memory), a master or because the setup of the write handler failed, the function returns C_ERR.在 master 保存和发送 rdb 文件时,slave 的状态是以下几种,所以在这期间的写命令都会保存在 slave 的 output buffer 。由于没有设置回调函数 , 数据并不会发送到 slave 上,仅存储在 master 为 slave 创建的 output buffer 内 。
#define SLAVE_STATE_WAIT_BGSAVE_START 6 /* We need to produce a new RDB file. */#define SLAVE_STATE_WAIT_BGSAVE_END 7 /* Waiting RDB file creation to finish. */#define SLAVE_STATE_SEND_BULK 8 /* Sending RDB file to slave. */
那么何时才会从 output buffer 中“刷入”slave 呢?直到 master 将 rdb 文件完全发送给 slave 后 , master 会在 sendBulkToSlave
函数中进行相关操作 。以下源码见:https://github.com/redis/redis/blob/5.0/src/replication.c#L876-L930void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) {// 此处省略部分源码// rdb 文件已完全发送给 slaveif (slave->repldboff == slave->repldbsize) {close(slave->repldbfd);slave->repldbfd = -1;aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE);putSlaveOnline(slave);}}void putSlaveOnline(client *slave) {slave->replstate = SLAVE_STATE_ONLINE;slave->repl_put_online_on_ack = 0;slave->repl_ack_time = server.unixtime; /* Prevent false timeout. */if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE,sendReplyToClient, slave) == AE_ERR) {serverLog(LL_WARNING,"Unable to register writable event for replica bulk transfer: %s", strerror(errno));freeClient(slave);return;}refreshGoodSlavesCount();serverLog(LL_NOTICE,"Synchronization with replica %s succeeded",replicationGetSlaveName(slave));}
此处会将 slave 状态改为 SLAVE_STATE_ONLINE
,并将repl_put_online_on_ack
置为0,(有没有很熟悉 , 对了,就是上面clientInstallWriteHandler
中判断的内容) 。同时也会设置回调函数sendReplyToClient
,将此前 master 为 slave 创建的 output buffer 中的写操作全部发送到 slave 上 。同时 slave 状态的变更,会使得后续 master 上的写操作可以正常的 push 到 slave 上了(直接,无需走 output buffer) 。总结本次我们通过
client-output-buffer-limit
参数,了解了其使用场景,并重点就主从同步时 output buffer 写入情况进行了源码的简单分析 。今天的学习就到这里 , 我们改天接着肝 。参考内容
- https://www.cnblogs.com/wangcp-2014/p/15505180.html
推荐阅读
- Docker | redis安装及测试
- 七 SpringBoot - Redis 缓存
- redis bitmap数据结构之java对等操作
- 带你认识JDK8中超nice的Native Memory Tracking
- Redis高可用之主从复制原理演进分析
- flinksql读写redis
- 追求性能极致:Redis6.0的多线程模型
- spring boot集成redis基础入门
- CentOS 7.9 安装 redis-6.2.0
- Redis实现布隆过滤器解析