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_REUSEADDRSO_EXCLUSIVEADDRUSE

使用SO_REUSEADDR

socketSO_REUSEADDR选项允许一个套接字强制绑定到另一个套接字正在使用的端口。第二个套接字调用 setsockopt 并将 optname 参数设置为,将SO_REUSEADDRoptval 参数设置为布尔值 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 负责的事情一样。

相关内容