阿里云首页

使用短连接访问Redis出现“Cannot assign requested address”错误

问题描述

应用程序通过短连接访问Redis实例时,出现以下报错:

Cannot assign requested address

问题原因

出现这种错误的应用程序使用的架构基本都是php-fpm加上phpredis,这种架构在并发量较大的情况下,处于TIME-WAIT状态下的TCP连接数较多,客户端无法分配出新的端口,则会出现“Cannot assign requested address”问题。

解决方案

针对这种情况有两种解决方案,一般情况下推荐您使用方案一:使用pconnect替换connect,对于一些特定场景(业务代码牵涉过多组件不易变更等场景),需要更快的满足高并发,可以使用方案二:修改客户端所在ECS实例的tcp_max_tw_buckets内核参数,避免出现“Cannot assign requested address”问题:

方案一:使用pconnect替换connect

此方案的思路是用长连接替代短连接,减少TCP连接,同时可以避免每次请求都会重新建立连接的问题,减少延时。

之前连接Redis的代码如下:

// 示例中的连接参数请根据业务实现情况修改。

$redis->connect('[$Hostname]', [$Port]);
$redis->auth('[$Inst_Password]');

说明:[$Hostname]、[$Port]和[$Inst_Password]为Redis实例的连接地址、端口号和密码,如何查看请参见查看连接地址

现使用pconnect替换connect,即使用persistent connection的方式连接,具体PhpRedis信息请参见PhpRedis官方文档

// PhpRedis应为5.3.0及以上版本,且建议使用这种pconnect初始化方式,避免断连时出现no auth问题。

$redis->pconnect('[$Hostname]', [$Port], 0, NULL, 0, 0, ['auth' => ['[$Inst_Password]']]);

方案二:修改客户端所在ECS实例的tcp_max_tw_buckets内核参数

此方案的思路是直接复用处于TIME-WAIT状态的端口,但是如果ECS和后端服务之间有重传,建连可能会失败,所以建议使用pconnect的方案。

  1. 连接客户端所在ECS实例,如何连接ECS实例请参见连接方式概述
  2. 执行以下命令,查看ip_local_port_range和tcp_max_tw_buckets参数。
    sysctl net.ipv4.tcp_max_tw_buckets net.ipv4.ip_local_port_range
    系统显示类似如下。
    net.ipv4.tcp_max_tw_buckets = 262144
    net.ipv4.ip_local_port_range = 32768 61000
  3. 执行以下命令,修改tcp_max_tw_buckets参数,确保tcp_max_tw_buckets的值比ip_local_port_range范围的值小。
    sysctl -w net.ipv4.tcp_max_tw_buckets=10000

更多信息

请忽略所有修改tcp_tw_reuse和tcp_tw_recycle的方法,这些方法对于使用了NAT或LVS的服务均不适用(tcp_tw_recycle在Linux 4.12上已经被弃用)。

适用于

  • 云数据库Redis
首页 使用短连接访问Redis出现“Cannot assign requested address”错误