认识 Redis client-output-buffer-limit 参数与源码分析( 二 )

由于函数默认返回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-L930
void 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 写入情况进行了源码的简单分析 。今天的学习就到这里,我们改天接着肝 。
参考内容
  1. https://www.cnblogs.com/wangcp-2014/p/15505180.html
【认识 Redis client-output-buffer-limit 参数与源码分析】

经验总结扩展阅读