Redis系列 | 阿里云 Redis 版数据库Lua脚本支持与限制
官方工单支持:
您好,
您的实例版本是16G集群版(8节点),
集群实例的命令限制您参考:
Lua使用限制
为了保证脚本里面的所有操作都在相同slot进行,云数据库Redis集群版本会对Lua脚本做如下限制:
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
2、所有key必须在1个slot上,否则返回错误信息,"
3、调用必须要带有key,否则直接返回错误信息, "
4、不支持发布订阅命令,包括:PSUBSCRIBE、PUBSUB、PUBLISH、PUNSUBSCRIBE、SUBSCRIBE、UNSUBSCRIBE。
原生的Lua脚本案例(不支持)
$script = <<<luascript local rate_key = KEYS[1] local limit = tonumber(ARGV[1]) -- 最大限制 local expire_time = ARGV[2] -- 过期时间 local result = redis.call('SETNX',rate_key,1); -- SETNX 只有不存在的时候才设置,返回1。否则返回0 if result == 1 then redis.call('expire',rate_key,expire_time) return 1 else if tonumber(redis.call("GET", rate_key)) >= limit then return 0 else redis.call("INCR", rate_key) return 1 end end luascript; $scriptSha = $redis->script('load', $script);
以上脚本在原生的Redis是可以运行的,但是在阿里云Redis则不行,直接返回false
解释一下官方的限制:
key的位置必须是KEYS array(不能使用Lua变量替换KEYS),而上面的脚本则是把KEYS[1] 赋值给了Lua变量 rate_key ,从而导致不能使用
最终修改兼容版本
local limit = tonumber(ARGV[1]) -- 最大限制 local expire_time = ARGV[2] -- 过期时间 local result = redis.call('SETNX',KEYS[1],1); -- SETNX 只有不存在的时候才设置,返回1。否则返回0 if result == 1 then redis.call('expire',KEYS[1],expire_time) return 1 else if tonumber(redis.call("GET", KEYS[1])) >= limit then return 0 else redis.call("INCR", KEYS[1]) return 1 end end luascript; $scriptSha = $redis->script('load', $script);
负载信息
"# Server redis_version:4.0.11 tcp_port:6379 uptime_in_seconds:5198246 uptime_in_days:60 hz:10 lru_clock:16284991 # Clients connected_clients:0 client_longest_output_list:0 client_biggest_input_buf:14 blocked_clients:0 # Memory used_memory:1569209784 used_memory_human:1.46G used_memory_rss:1856352256 used_memory_rss_human:1.73G used_memory_peak:1672249240 used_memory_peak_human:1.56G used_memory_overhead:954746082 used_memory_overhead_human:910.52M used_memory_startup:161978704 used_memory_startup_human:154.47M used_memory_dataset:614463702 used_memory_dataset_human:586.00M used_memory_lua:345088 used_memory_lua_human:337.00K maxmemory:17179869184 maxmemory_human:16.00G maxmemory_policy:volatile-lru mem_fragmentation_ratio:1.45 mem_allocator:jemalloc-5.1.0 active_defrag_running:0 lazyfree_pending_objects:0 # Stats total_connections_received:160659957 total_commands_processed:777588709 instantaneous_ops_per_sec:2763 total_net_input_bytes:81642748753 total_net_output_bytes:305788723191 instantaneous_input_kbps:327 instantaneous_output_kbps:1346 rejected_connections:0 sync_full:8 sync_partial_ok:0 sync_partial_err:0 expired_keys:38333350 evicted_keys:0 keyspace_hits:181375543 keyspace_misses:74435657 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:9565 migrate_cached_sockets:0 # Replication connected_slaves:1 master_repl_offset:10266296484 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:33554432 repl_backlog_first_byte_offset:10232742053 repl_backlog_histlen:33554432 # CPU used_cpu_sys:39038.91 used_cpu_user:45386.70 used_cpu_sys_children:9.07 used_cpu_user_children:100.86 # Cluster cluster_enabled:0 databases:256 nodecount:8 # Keyspace db0:keys=5856727,expires=5856723,avg_ttl=14963354 db10:keys=1,expires=0,avg_ttl=0 "
- 上一篇 »Java面试之Redis
- 下一篇 »PHP REDIS GEO 经纬度