由于部署架构的不同,相对标准架构来说,集群架构的实例在原生Redis命令的支持上有一定的区别,本文介绍集群架构实例的命令使用限制。

支持的命令

说明 集群架构的Redis实例支持直连模式代理模式,如需通过JedisCluster使用multi或exec方法,请使用代理模式。

不支持的命令

  • SWAPDB
  • CLIENT ID
  • SORT(BYGET参数)

受限的命令

说明 如需在集群架构实例中执行下述受限制的命令,请使用hash tag确保命令所要操作的key都分布在1个hash slot中,hash tag的详细用法请参见Redis官方文档
命令族 具体命令
HyperLogLog PFMERGE、PFCOUNT
Keys RENAME、RENAMENX、SORT
Lists RPOPLPUSH、BRPOP、BLPOP、BRPOPLPUSH
Scripting EVAL、EVALSHA、SCRIPT EXISTS、SCRIPT FLUSH、SCRIPT KILL、SCRIPT LOAD
Strings MSETNX
Transaction DISCARD、EXEC、MULTI、UNWATCH、WATCH

SELECT命令的限制

连接模式 说明
代理模式 支持,需要注意的是某些开源Redis客户端(例如stackExchange.redis)由于其误判导致无法正常执行SELECT命令,您可以先将cluster_compat_enable参数设置为0(即关闭原生Redis Cluster语法兼容),然后重启客户端应用后再进行尝试。具体操作,请参见设置实例参数。您也可以更其他支持该命令的客户端,例如Jedis客户端
直连模式 不支持,主流客户端(例如Jedis客户端)的自身限制导致。

集群架构中Lua脚本的限制

警告 由于集群架构对Lua脚本的使用存在一定的限制,在将实例变更至集群架构时(通过变更实例配置实现),Lua脚本可能因脚本内容不符合限制而发生丢失,请务必提前备份。

Redis Cluster对使用Lua脚本增加了一些限制,云数据库Redis集群版在这个基础上存在如下额外限制:

说明 如果发现无法执行Eval的相关命令,例如提示ERR command eval not support for normal user,请将实例的小版本升级至最新。具体操作,请参见升级小版本
  • 所有key必须在一个slot上,否则返回错误信息:
    -ERR eval/evalsha command keys must be in same slot\r\n
    说明 您可以通过CLUSTER KEYSLOT命令获取目标key的哈希槽(hash slot)。
  • 对单个节点执行SCRIPT LOAD命令时,不保证将该Lua脚本存入至其他节点中。
  • 不支持发布订阅命令,包括PSUBSCRIBEPUBSUBPUBLISHPUNSUBSCRIBESUBSCRIBEUNSUBSCRIBE
  • 不支持UNPACK函数。

若您能够在代码中确保所有操作都在相同slot(如果不能保障这一点,执行会出错),且希望打破Redis集群的Lua限制,可以在控制台将script_check_enable修改为0,则后端不会对脚本进行校验,但仍需要使用KEYS数组至少传递一个key,供代理节点执行路由转发。具体操作,请参见设置实例参数

代理模式的额外限制

  • 所有key都应该由KEYS数组来传递,redis.call/pcall中调用的Redis命令,key的位置必须是KEYS array(不能使用Lua变量替换KEYS),否则直接返回错误信息:
    -ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array\r\n
    正确与错误命令示例如下:
    # 本示例的准备工作需执行如下命令
    SET foo foo_value
    SET {foo}bar bar_value
    
    # 正确示例
    EVAL "return redis.call('mget', KEYS[1], KEYS[2])" 2 foo {foo}bar
    
    # 错误示例
    EVAL "return redis.call('mget', KEYS[1], '{foo}bar')" 1 foo
    EVAL "return redis.call('mget', KEYS[1], ARGV[1])" 1 foo {foo}bar
  • 调用必须要带有key,否则直接返回错误信息:
    -ERR for redis cluster, eval/evalsha number of keys can't be negative or zero\r\n
    正确与错误命令示例如下:
    # 正确示例
    EVAL "return redis.call('get', KEYS[1])" 1 foo
    
    # 错误示例
    EVAL "return redis.call('get', 'foo')" 0
  • 不支持在MULTI、EXEC事务中使用EVAL、EVALSHA、SCRIPT系列命令。
说明 若您需要使用代理模式下受限的部分功能,您可以尝试开通使用云数据库Redis集群版的直连模式。但是由于云数据库Redis集群版在迁移、变配时都会通过proxy代理迁移数据,直连模式下不符合代理模式的Lua脚本会迁移、变配失败。

建议您在直连模式下使用Lua脚本时应尽可能符合代理模式下的限制规范,避免后续Lua脚本迁移、变配失败。

其他限制

  • 执行CLIENT LIST命令会列出所有连接到该代理节点的连接信息。返回结果解释如下:
    • idageidleaddrfdnamedbmultiomemcmd字段和原生Redis的含义一致。
    • subpsub在代理节点上没有区分,统一为1或0。
    • qbufqbuf-freeobloll字段目前没有具体意义。
  • CLIENT KILL命令目前支持的形式为:client kill ip:portclient kill addr ip:port
  • 对于集群架构实例,在代理模式下,为了兼容主从架构,事务会被拆分成多个子事务执行,此时无法保证事务的原子性;在直连模式下,与开源Redis Cluster行为一致,即严格要求事务所操作的key均在同一slot。
    注意 在代理模式下,当使用WATCH或事务内有多key命令(如MSET)时,事务不会被拆分,严格要求事务所操作的Key均在同一Slot,此时可以保证事务的原子性。
    • 多key命令包括:DEL、SORT、MGET、MSET、BITOP、EXISTS、MSETNX、RENAME、 RENAMENX、BLPOP、BRPOP、RPOPLPUSH、BRPOPLPUSH、SMOVE、SUNION、SINTER、SDIFF、SUNIONSTORE、SINTERSTORE、SDIFFSTORE、ZUNIONSTORE、ZINTERSTORE、 PFMERGE、PFCOUNT。
    • 不允许在事务中使用的命令为:WATCH、UNWATCH、RANDOMKEY、KEYS、SUBSCRIBE、 UNSUBSCRIBE、PSUBSCRIBE、PUNSUBSCRIBE、PUBLISH、PUBSUB、SCRIPT、EVAL、 EVALSHA、SCAN、ISCAN、DBSIZE、ADMINAUTH、AUTH、PING、ECHO、FLUSHDB、 FLUSHALL、MONITOR、IMONITOR、RIMONITOR、INFO、IINFO、RIINFO、CONFIG、 SLOWLOG、TIME、CLIENT。