redis-server 運行多次會在同一連接埠上綁定多個偵聽套接字嗎?

redis-server 運行多次會在同一連接埠上綁定多個偵聽套接字嗎?

在 Windows Server 2019 上,在 WSL 下我第二次錯誤地執行redis-server,而且它沒有報告綁定偵聽套接字失敗。這是輸出netstat

C:\Users\Administrator>netstat -ano | grep 6379 | grep LISTEN
  TCP    0.0.0.0:6379           0.0.0.0:0              LISTENING       11080
  TCP    127.0.0.1:6379         0.0.0.0:0              LISTENING       13292
  TCP    [::]:6379              [::]:0                 LISTENING       11080
  TCP    [::1]:6379             [::]:0                 LISTENING       13292

兩個問題:

  1. 這怎麼可能?
  2. 如何選擇要連線到的實例redis-cli

謝謝。

編輯

我第三次運行它只是為了檢查,這是輸出netstat

C:\Users\Administrator>netstat -ano | grep 6379 | grep LISTEN
  TCP    0.0.0.0:6379           0.0.0.0:0              LISTENING       13916
  TCP    0.0.0.0:6379           0.0.0.0:0              LISTENING       11080
  TCP    127.0.0.1:6379         0.0.0.0:0              LISTENING       13292
  TCP    [::]:6379              [::]:0                 LISTENING       11080
  TCP    [::]:6379              [::]:0                 LISTENING       13916
  TCP    [::1]:6379             [::]:0                 LISTENING       13292

這些是任務管理器中的進程條目: 在此輸入影像描述

答案1

如果插座有SO_REUSEADDR設定標誌,然後多個進程將能夠綁定到給定連接埠。

使用SO_REUSEADDRSO_EXCLUSIVEADDRUSE

使用SO_REUSEADDR

套接字選項SO_REUSEADDR允許套接字強制綁定到另一個套接字正在使用的連接埠。第二個套接字呼叫setsockopt,並將optname 參數設定為,SO_REUSEADDR並將optval 參數設為布林值TRUE,然後在與原始套接字相同的連接埠上呼叫bind。

這是為了允許服務在多個獨立進程之間共享負載,並且只有在服務能夠正確處理此問題時才應使用...Redis 很可能是支援此功能的服務之一(並預設啟用它) )。

net.c:

static int redisSetReuseAddr(redisContext *c) {
    int on = 1;
    if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
        redisNetClose(c);
        return REDIS_ERR;
    }
    return REDIS_OK;
}

static int redisCreateSocket(redisContext *c, int type) {
    redisFD s;
    if ((s = socket(type, SOCK_STREAM, 0)) == REDIS_INVALID_FD) {
        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
        return REDIS_ERR;
    }
    c->fd = s;
    if (type == AF_INET) {
        if (redisSetReuseAddr(c) == REDIS_ERR) {
            return REDIS_ERR;
        }
    }
    return REDIS_OK;
}

如果需要確定連接到哪台伺服器,可以使用Redis指令INFO server,然後尋找該process_id欄位。

或者,您可以netstat -ano在 Windows(netstat -tnp在 Linux 上)上使用來確定給定客戶端連接埠的伺服器 PID(但不是客戶端 PID)。

我不相信有一個簡單的作業系統層級的方法來確定這種關係。


如果您有多個伺服器實例,每個實例使用不同的配置和/或數據,則會出現配置錯誤:應該修正 - 即:不要同時執行多個服務,或為每個服務使用不同的連接埠。

這不是 Redis 負責的事情,就像選擇監聽連接埠不是 Redis 負責的事情一樣。

相關內容