一.redis中原生之行lua
基本命令:https://www.runoob.com/redis/redis-scripting.html
1.准备一个lua脚本,test.lua
local key1 = KEYS[1]
local val1 = ARGV[1]
local key2 = KEYS[2]
local val2 = ARGV[2]
local res = redis.call("get",key1)
if (res == 18)
then
redis.call("set",key1,val1)
else
redis.call("set",key1,10)
end
return redis.call("get",key1)
如果是容器,先进入 redis 容器之行
redis-cli -h 127.0.0.1 -p 6379 eval "$(cat test.lua)" 2 age name 15 stb
# 或者直接写代码也行,比如
redis-cli -h 127.0.0.1 -p 6379 eval "return {KEYS[1],ARGV[1]}" 1 name stb
如果不想每次都执行 redis-cli,那就直接先进入redis命令行,就可以省略redis-cli -h 127.0.0.1 -p 6379
,直接执行eval 命令,如下
redis-cli -h 127.0.0.1 -p 6379
eval "$(cat test.lua)" 1 age 15
# 或者直接写代码也行,比如
eval "return {KEYS[1],ARGV[1]}" 1 name stb
解释
命令后面的 1 ,代表后面有几个 key参数,如果是 2 就是两个参数,比如上面,age和name是两个标识,就是 2,后面的就是对应的内容
golang中使用
package main
import (
"context"
"log"
"github.com/redis/go-redis/v9"
)
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379",
DB: 0, // 默认DB 0
})
defer rdb.Close()
ctx := context.Background()
// 普通执行
// 其他命令同理
// res, err := rdb.Eval(ctx, "return {KEYS[1],ARGV[1]}", []string{"name"}, "stb").Result()
// 多行脚本执行
res, err := rdb.Eval(ctx, `
local key1 = KEYS[1]
local key2 = KEYS[2]
local val1 = ARGV[1]
local val2 = ARGV[2]
local res = redis.call("get",key1)
if (res == 18)
then
redis.call("set",key1,val1)
else
redis.call("set",key1,10)
end
return redis.call("get",key2)
`, []string{"name", "age"}, "stb", 18).Result()
if err != nil {
return
}
log.Println("res=:", res)
}
解释:
其实就是 lua 的代码,在redis 中用对应的命令去执行,比如 eval,把lua 代码看成一段字符串,然后用redis eval 命令执行,加上对应的参数即可
问题解析
1.执行错误会继续执行
2.eval每次都会将完整的脚本传递,网络开销大,应该先用script load 预先缓存,然后用反馈的 哈嘻值,使用 evalsha来执行
// 输入该脚本
# redis-cli script load "$(cat test.lua)"
"bdb8680ea6967110d89ea6e574b6cf4b2b3e6507" // 这个用来执行的标识
// 执行该脚本
# redis-cli evalsha bdb8680ea6967110d89ea6e574b6cf4b2b3e6507 2 age name 15 17
(integer) 32 // 反馈结果