Redis端口失效诡异门(redis突然打不开)
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时,不要使用靠近随机端口范围的自定义端口号,这样可以避免诸如端口冲突等问题的发生。
相关文章