1、直接使用EVAL执行,不算在“更好”的范围内,不做讨论。
2、正常判断式:先判断脚本存不存在,再进行操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| /**
* 向Redis注册Lua脚本
*
* @param Redis $redis
* @param $file
*
* @return bool|mixed|string
*/
function load_lua_script(Redis $redis, $file) {
if (!is_file($file)) {
return false;
}
$sha1 = sha1_file($file);
if ($redis->script('EXISTS', $sha1)[0] == 1) {
return $sha1;
} else {
return $redis->script('LOAD', file_get_contents($file));
}
}
$script_sha = load_lua_script($redis, '/path/to/lua_script.lua');
$reuslt = $redis->evalSha($script_sha, $args, $key_number);
|
3、触发式执行:如果执行失败了,才LOAD脚本,并重新运行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| /**
* 执行Lua脚本
*
* @param Redis $redis
* @param $file
* @param $args
* @param $numKeys
*
* @return bool|mixed|string
*/
function run_lua_script(Redis $redis, $file, $args, $numKeys) {
if (!is_file($file)) {
return false;
}
$sha1 = sha1_file($file);
for ($run_number = 0; $run_number < 3; $run_number++) {
$redis_result = $redis->evalSha($sha1, $args, $numKeys);
// 检测脚本是否不存在,如果不存在,则加载,并重新执行
if (substr($redis->getLastError(), 0, 8) === 'NOSCRIPT') {
echo 'LOAD' . PHP_EOL;
$sha1 = $redis->script('LOAD', file_get_contents($file));
$redis->clearLastError();
continue;
}
return $redis_result;
}
return false;
}
$reuslt = run_lua_script($redis, '/path/to/lua_script.lua', $args, $key_number);
|
测试:
Lua脚本:
1
2
3
4
5
| -- lua_script.lua
local value = redis.call('INCRBY', KEYS[1], ARGV[1])
return 'hello ' .. value
|
二号脚本测试运行10000次:8万次单程 IO 运行 0.9738 秒。
三号脚本测试运行10000次:4万次单程 IO 运行 0.6284 秒。
显而易见,触发式脚本可以更好的节约IO、以高的性能运行。