Redis端口失效诡异门(redis突然打不开)

2023-05-16 16:41:28 端口 失效 打不开

Redis端口失效诡异门

Redis是一款流行的数据存储系统,常用于缓存、消息队列、全文搜索等应用场景。在使用Redis时,我们通常会通过端口号来连接Redis服务器进行数据读写操作。但是,最近有网友反映,他们的Redis端口失效,造成无法对数据进行读写操作,经过排查后发现是一个诡异的bug导致的。

我们来看一下Redis的端口号配置方式。在Redis的配置文件redis.conf中有一行端口配置:

port 6379

这里的6379就是Redis默认的端口号,我们可以自定义端口号来连接Redis服务。比如,我们将端口号修改为6380:

port 6380

如果Redis服务启动成功,我们就可以通过该端口号来连接Redis服务器。但是,最近有一些用户反映,在Redis服务启动后,他们自定义的端口号无法连接到Redis服务器,而6379端口号是可以连接的。这是否说明自定义的端口号出现问题了呢?经过排查发现,问题不在于自定义的端口号。

在分析这个问题的时候,我们首先想到了iptables防火墙。iptables是Linux系统自带的防火墙,它可以对网络流量进行过滤和转发。因此,我们可能会认为iptables防火墙阻止了自定义端口号的连接,但是经过排查发现,iptables防火墙规则是开放的,不会阻止自定义端口号的连接。

接着,我们又检查了Redis服务是否正常启动,发现6379端口是可以连接的,因此排除了Redis服务启动异常的可能性。

我们进一步分析了Redis服务的源码,终于发现了问题所在:Redis源码中使用了一种随机端口号分配的策略,这种策略可能导致与用户自定义端口号冲突。

Redis的源码中有以下一段代码:

/* bind to all addresses if no bind address was specified */

if (server.bindaddr_count == 0) server.bindaddr[0] = NULL;

/* TCP backlog queue */

if (listen(server.fd, server.tcp_backlog) == -1) {

serverLog(LL_WARNING, “Fled to listen on TCP port: %s”,

strerror(errno));

return C_ERR;

}

serverLog(LL_NOTICE,”Ready to accept connections”);

aeCreateFileEvent(server.el, server.fd, AE_READABLE, acceptTcpHandler,NULL);

int j;

/* Associate redisFile structures with read/write handlers. */

for (j = 0; j

if (aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE,

acceptHandler, NULL) == AE_ERR)

{

serverPanic(

“Unrecoverable error creating server.ipfd file event.”);

}

}

源码中的服务器启动函数listenToPort(),使用了随机的端口号来分配IP地址和端口号。其中,在服务器开始监听端口号之前,需要调用SO_REUSEADDR选项。SO_REUSEADDR指的是在同一台主机上,如果两个进程绑定相同的IP地址和端口号,则可以重复使用该端口号。而端口号的范围是0-65535,因此,如果我们的自定义端口号与随机分配的端口号相同,就会导致连接失败的问题。

针对这个问题,我们可以采取以下解决方案:

1. 避免使用靠近随机端口范围的自定义端口号,例如使用6888或者7788这样的端口号。

2. 修改Redis源码,在listenToPort()函数前增加判断逻辑,判断自定义端口号是否已经被占用,如果已经被占用,则不采用随机分配端口号的策略。

Redis端口失效这个问题虽然诡异,但是我们只要深挖根源,就能找到解决方案。再次提醒大家,在使用Redis时,不要使用靠近随机端口范围的自定义端口号,这样可以避免诸如端口冲突等问题的发生。

相关文章