本文介绍访问云原生内存数据库Tair与云数据库Redis版时的常见报错与解决方法。
报错概览
Redis通用异常
ERR illegal address
可能原因:未将客户端的IP地址添加至Tair实例的白名单中。
解决方法:将客户端的IP地址添加入至Tair实例的白名单中,具体操作请参见连接诊断。
ERR sentinel compatibility mode is disabled
可能原因:未开启Tair实例的Sentinel兼容。
解决方法:在控制台开启Sentinel兼容,具体操作请参见开启Sentinel兼容。
ERR max number of clients reached
可能原因:客户端的连接数超过了Tair实例的最大连接数。
NOAUTH Authentication required
可能原因:Tair实例设置了密码鉴权,但客户端没有提供密码。
WRONGPASS invalid username-password pair
可能原因:密码错误。
ERR invalid password
可能原因:密码错误。
Connection reset by peer
可能原因:客户端连接被关闭,通常是由于客户端缓冲区异常而关闭客户端连接。
解决方法:检查应用侧代码或调整客户端Buffer的大小,更多信息请参见Client buffer exception。
UnknownHostException
或failed to connect: xxx.redis.rds.aliyuncs.com could not be resolved
。
可能原因:客户端无法正常解析Tair实例的域名地址。
解决方案:请设置正确的DNS服务器地址,更多信息请参见解决因域名解析失败导致的连接问题。
OOM command not allowed when used memory > 'maxmemory'
WRONGTYPE Operation against a key holding the wrong kind of value
可能原因:命令使用错误,例如对String数据类型执行HASH
命令。
解决方法:修改错误代码或命令,更多信息请参Redis Commands。
ERR unknown command 'xxx'
可能原因:Tair不存在您调用的命令。
ERR command 'xxx' not support for your account
可能原因:阿里云禁止用户执行某些Tair命令,或您手动在#no_loose_disabled-commands参数中配置了禁止执行的命令。更多信息请参见Tair命令支持与限制和禁用高风险命令。
解决方法:若需执行您禁用的命令,您可以在#no_loose_disabled-commands参数中删除对应命令。
NOPERM this user has no permissions to run the 'xxx'
可能原因:阿里云禁止用户执行某些Tair命令,或您手动在#no_loose_disabled-commands参数中配置了禁止执行的命令。更多信息请参见Tair命令支持与限制和禁用高风险命令。
解决方法:若需执行您禁用的命令,您可以在#no_loose_disabled-commands参数中删除对应命令。
ERR FLUSHDB is not allowed in migrating mode
可能原因:Tair云盘集群架构实例在执行增加或减少数据节点时,禁止使用FLUSHDB
或FLUSHALL
命令。
解决方法:等待Tair云盘集群架构实例执行增加或减少数据节点结束,更多信息请参见调整云盘实例的分片数量。
ERR READONLY you can't write against a read only instance
可能原因:Tair实例在主备切换、升降配或小版本升级时,将出现秒级的连接闪断和30秒以内的只读状态。
解决方法:属于正常现象,实例会自动恢复,您无需进行任何操作。请提前为您的应用设计重连机制和异常处理的能力,更多信息请参见升级实例配置。
Proxy(代理模式)通用异常
ERR client ip is not in whitelist
可能原因:未将客户端的IP地址添加至Tair实例的白名单中。
解决方法:将客户端的IP地址添加入至Tair实例的白名单中,具体操作请参见连接诊断。
NOWRITE You can't write against a non-write redis
或NOREAD You can't read against a non-read redis
。
可能原因:实例处于欠费或到期状态,实例状态显示为已锁定。
解决方法:对账号进行充值,或对到期的实例进行续费,更多信息请参见到期与欠费。
ERR syntax error
可能原因:命令语法错误,例如需要传入4个参数,实际仅传入3个参数。
解决方法:检查命令格式是否正确,更多信息请参Redis Commands。
ERR no such db node
可能原因:使用阿里云自研的Tair命令时,传入的db node
错误。
解决方法:传入正确的db node
,db node
需小于分片数量,更多信息请参见阿里云自研的Tair命令。
ERR 'xxx' command keys must in same slot
可能原因:在Tair集群架构实例中,通过事务或脚本执行命令时要求所有Key必须在同一个Slot中,否则将返回上述错误。
CLUSTER KEYSLOT
命令获取目标Key的Hash Slot。ERR for redis cluster, eval/evalsha number of keys can't be negative or zero
可能原因:执行EVAL
和EVALSHA
命令未传入Key或numkeys参数的值未大于0。
解决方法:执行EVAL
和EVALSHA
命令时,至少需要传入一个Key且numkeys参数的值大于0,更多信息请参见Lua脚本基本语法。
ERR request refused, too many pending request, now count xxx, beyond threshold xxx
可能原因:由于客户端使用了不合理的Pipeline,Tair后端堆积了过多未处理的Request,新请求被拒绝。
解决方法:减少Pipeline的请求数量。
ERR redis temporary failure
可能原因:部分Tair子实例访问超时,可能是网络抖动、连接数到达上限导致断链、实例正在进行主备切换或执行慢查询等导致。
解决方法:属于正常现象,实例会自动恢复,您无需进行任何操作。请提前为您的应用设计重连机制和异常处理的能力。
ERR redis temporary failure (ErrorCode 7002)
可能原因:部分Tair子实例访问超时,可能是实例正在变配或正在进行主备切换导致。
解决方法:属于正常现象,实例会自动恢复,您无需进行任何操作。请提前为您的应用设计重连机制和异常处理的能力。
Lua脚本与事务(Transaction)
NOSCRIPT No matching script. Please use EVAL.
可能原因:使用EVALSHA
命令时,若SHA1值对应的脚本未缓存至Tair中。
解决方法:通过EVAL
命令或SCRIPT LOAD
命令将目标脚本缓存至Tair中后进行重试,更多信息请参见处理NOSCRIPT错误。
BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
可能原因:处理Lua脚本超时。
解决方法:通过SCRIPT KILL命令终止Lua脚本或等待Lua脚本执行结束,更多信息请参见处理Lua脚本超时。
ERR command eval not support for normal user
可能原因:无法执行EVAL
的相关命令。
解决方法:请将实例的小版本升级至最新,具体操作请参见升级小版本。
ERR eval/evalsha command keys must be in same slot
可能原因:Lua脚本操作的Key不在同一个Slot(槽)中,该报错通常产生于集群实例中。
解决方法:改造Lua脚本,您可以通过CLUSTER KEYSLOT
命令获取目标Key的Hash Slot,更多信息请参见集群中Lua脚本的限制。
ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array
可能原因:Proxy(代理)节点的Lua脚本限制。
解决方法:所有Key都应该由KEYS数组来传递,例如EVAL "return redis.call('mget', KEYS[1], KEYS[2])" 2 foo {foo}bar
,不能使用Lua变量替换KEYS,更多信息请参见集群中Lua脚本的限制。
EXECABORT Transaction discarded because of previous errors
可能原因:事务中的命令执行失败,可能是命令语法错误或运行错误等。
解决方法:检查代码逻辑,修复错误命令。
Jedis客户端
Could not get a resource from the pool
可能原因:无法从连接池获取到Jedis连接。
解决方法:增大连接数或检查是否有慢查询,更多信息请参见Could not get a resource from the pool。
java.net.SocketTimeoutException: connect timed out
可能原因:客户端连接Tair实例超时。
解决方法:更多信息请参见Connection timeout。
java.net.SocketTimeoutException: Read timed out
可能原因:Jedis API调用超时。
解决方法:适当增大超时时间或进行实例诊断,更多信息请参见Client read /write timeout。
No reachable node in cluster
可能原因:JedisCluster地址无法访问。
解决方法:如果是首次访问Tair实例,请检查是否将客户端的IP地址添加至Tair白名单中或客户端的网络情况;若不是首次访问Tair实例,可以进行实例诊断,进行问题定位。
Caused by: java.lang.NumberFormatException: For input string: "6379@13028"
可能原因:Jedis 2.8.0及以下版本引入了ClusterNodeInformationParser
来解析cluster slots
返回值,但Redis后续更改了此命令返回值类型,所以报错NumberFormatException
。
解决方法:将Jedis升级至2.9.0及以上版本。
No more cluster attempts left
可能原因:JedisCluster在API超时之后会默认重试5次(MaxAttempts,默认为5),并且在均失败之后抛出此错误。
解决方法:适当增大超时时间或进行实例诊断。
Unexpected end of stream
可能原因:Jedis缓冲区异常。
解决方法:检查是否有多线程共用Jedis代码或客户端Buffer用完造成服务端断连,更多信息请参见Client buffer exception。
java.lang.Long cannot be cast to java.util.List
可能原因:在多线程环境中使用Jedis,Jedis本身存在线程安全问题。
解决方法:使用JedisPool,而非Jedis,更多信息请参见JedisPool资源池优化。
Broken pipe (Write failed)
可能原因:在Jedis单连接模式(未使用JedisPool)下超时后,客户端关闭了Socket,此时若您继续调用读写接口写入数据,会返回该报错。
解决方法:使用JedisPool,而非Jedis,更多信息请参见JedisPool资源池优化。
No way to dispatch this command to Redis Cluster because keys have different slots
可能原因:JedisCluster操作的Key不在同一个Slot(槽)中。
Lettuce客户端
Connection to xxx not allowed. This Partition is not known in the cluster view.
可能原因:Lettuce客户端在默认情况下,配置为refreshOption = null , validateClusterNodeMembership = true
,表示开启validateClusterNodeMembership
检测。在Tair实例地址发生路由变化后,由于没有开启refreshOption
,即不会更新路由表,此时validateClusterNodeMembership
检测就会返回该报错。
解决方法:配置refreshOption
选项,更多信息请参见Lettuce连接代码示例。
io.lettuce.core.RedisConnectionException: Unable to connect xxx
可能原因:客户端连接Tair实例超时。
解决方法:如果是首次访问Tair实例,请检查是否将客户端的IP地址添加至Tair白名单中或客户端的网络情况;若不是首次访问Tair实例,可以进行实例诊断,进行问题定位。
java.nio.channels.UnresolvedAddressException
可能原因:大概率是Netty版本冲突。
解决方法:检查Netty依赖,建议选择较高的版本,更多信息请参见Spring-boot issues。
ERR Unknown sentinel subcommand 'master'
可能原因:Lettuce在master-replica Sentinel模式下会向Redis实例发送Sentinel master/slave
命令,而Tair实例在Sentinel兼容模式下仅支持Sentinel get-master-addr-by-name
命令,故产生该报错。
解决方法:修改代码为普通模式(非Sentinel),Tair采用自研的高可用服务HA组件,无需Sentinel。
Redisson客户端
org.redisson.client.RedisConnectionException: Unable to connect to Redis server xxx
可能原因:客户端连接Tair实例超时。
解决方法:如果是首次访问Tair实例,请检查是否将客户端的IP地址添加至Tair白名单中或客户端的网络情况;若不是首次访问Tair实例,可以进行实例诊断,进行问题定位。
No enum constant org.redisson.cluster.ClusterNodeInfo.Flag.NOFAILOVER
可能原因:Redisson低版本Bug,更多信息请参见Redisson issue。
解决方法:将Redisson升级至3.11.6及以上版本。
Spring Data Redis客户端
NOPERM this user has no permissions to run the 'config|get' command
可能原因:Spring Data Redis的KeyspaceEventMessageListener功能在服务端不支持CONFIG
命令,通常在启动客户端时会产生该报错。
解决方法:可通过设置keyspaceNotificationsConfigParameter可以绕过此问题,更多信息请参见Spring Data Redis。
StackExchange.Redis客户端
Multiple databases are not supported on this server; cannot switch to database
可能原因:集群架构不支持执行SELECT
命令。
解决方法:将cluster_compat_enable
参数设置为0(即关闭原生Redis Cluster语法兼容),具体操作请参见设置实例参数,然后重启客户端应用后重试。
Predis客户端
Error while reading line from the server.
可能原因:读取超时,您可能正在执行一个慢查询。
解决方法:适当增大超时时间或将客户端的read_write_timeout
参数改为0
或-1
,更多信息请参见Predis questions。
phpredis客户端
Cannot assign requested address
可能原因:客户端通过短连接访问Tair实例时,产生该报错。
解决方法:使用pconnect
替换connect
的连接方式,或修改客户端所在ECS实例的tcp_max_tw_buckets
内核参数,更多信息请参见Cannot assign requested address。
redis protocol error, got ' ' as reply type byte
可能原因:phpredis低版本Bug,更多信息请参见phpredis issues。
解决方法:将phpredis升级至最新版。
php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution
可能原因:客户端无法正常解析Tair实例的域名地址。
解决方案:请设置正确的DNS服务器地址,更多信息请参见解决因域名解析失败导致的连接问题。
Go-redis客户端
panic: got 4 elements in cluster info address, expected 2 or 3
可能原因:使用的Go-redis客户端版本与Tair版本不匹配,更多信息请参见Go-redis issues。
解决方案:使用对应版本的Go-redis客户端访问Tair实例。Tair(兼容Redis 6.0及以下版本)请选择Go-redis v8.0及以下版本。