認識 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

推薦閱讀