19.1 redis-lua 库
安装
$ sudo luarocks install redis-lua
redis-lua 库 redis客户端端编程示例:
local params = {
host = '127.0.0.1',
port = 6380,
}
local client = redis.connect(params)
--string类型的操作
client:set('foo', 'bar')
local value = client:get('foo')
print(value)
--list操作
client:lpush("lua_list_key", "123", "456")
client:rpush("lua_list_key", "ABC")
local list_array = client:lrange("lua_list_key", 0, -1)
for key, val in pairs(list_array)
do
print("key = ", key)
print("val = ", val)
end
--hash操作
client:hset("lua_hash_key", "name", "zhang3")
client:hset("lua_hash_key", "age", 18)
local name = client:hget("lua_hash_key", "name")
print("name = ".. name);
local age = client:hget("lua_hash_key", "age")
print("age = " .. age);
local hash_zhang3 = client:hgetall("lua_hash_key")
for key, val in pairs(hash_zhang3)
do
print("key = ", key)
print("val = ", val)
end
--set 操作
client:sadd("wbq_friends", "chenhe", "lichen", "marong", "dengchao")
client:sadd("sz_friends", "sz_wife", "marong")
local wbq_sz_friends = client:sinter("wbq_friends", "sz_friends")
for key, val in pairs(wbq_sz_friends)
do
print("key = ", key)
print("val = ", val)
end
--zset 操作
client:zadd("music_top_zset", 98, "music01")
client:zadd("music_top_zset", 91, "music02")
client:zadd("music_top_zset", 97, "music03")
local top_musics = client:zrange("music_top_zset", 0, -1)
for key, val in pairs(top_musics)
do
print("key = ", key)
print("val = ", val)
end
print("----- use withscores ----")
local top_musics = client:zrange("music_top_zset", 0, -1, {withscores=true})
for key, val in pairs(top_musics)
do
print("key = ", key)
for index, value in pairs(val)
do
if (index == 1) then
print("member = ", value)
end
if (index == 2) then
print("socre = ", value)
end
end
end
--key 操作
client:del("foo")
client:del("lua_list_key")
client:del("wbq_friends")
client:del("sz_friends")
client:del("music_top_zset")
19.2 redis 嵌入lua脚本
Lua 脚本功能是 Reids 2.6 版本的最大亮点, 通过内嵌对 Lua 环境的支持, Redis 解决了长久以来不能高效地处理 CAS (check-and-set)命令的缺点, 并且可以通过组合使用多个命令, 轻松实现以前很难实现或者不能高效实现的模式。
本章先介绍 Lua 环境的初始化步骤, 然后对 Lua 脚本的安全性问题、以及解决这些问题的方法进行说明, 最后对执行 Lua 脚本的两个命令 ——EVAL和EVALSHA的实现原理进行介绍。
19.2.1 redis直接执行lua脚本文件
local msg = "hello lua in redis"
return msg
这是非常简单的,第一行代码定义了一个本地变量msg存储我们的信息, 第二行代码表示 从redis 服务端返回msg的值给客户端。 保存这个文件到hello_redis.lua,像这样去运行:local msg = “hello lua in redis”
redis-cli EVAL "$(cat hello.lua)" 0
运行这段代码会打印”hello lua in redis”, EVAL在第一个参数是我们的lua脚本, 这我们用cat命令从文件中读取我们的脚本内容。第二个参数是这个脚本需要访问的Redis 的键的数字号。我们简单的 “Hello Script” 不会访问任何键,所以我们使用0.
19.2.2 访问键和参数
案例1
假设我们要建立一个URL简写服务器。我们就要去存储每条进入的URL并返回一个唯一数值,以便以后通过这个数值访问到该URL。
我们将利用Lua脚本立即从Redis中用INCRand获取一个唯一标识ID,以这个标识ID作为URL存储于一个哈希中的键值:
local ret = redis.call("SET", KEYS[1], ARGV[1])
redis.call("HSET", KEYS[2], "name", ARGV[2])
return ret
把以上代码保存为文件“redis_script.lua”中。
执行:
redis-cli -p 6380 EVAL "$(cat redis_script.lua)" 2 my_string_key my_hash_key zhang3 li4
在EVAL语句中,2指出需要传入的KEY的个数,后面跟着需要传入的两个KEY,最后传入是ARGV的值。在Redis中执行Lua脚本时,Redis-cli会检查传入KEY的个数,除非传入的完全是命令。
以上指令相当于脚本
local ret = redis.call("SET", "my_string_key", "zhang3")
redis.call("HSET", "my_hash_key", "name", "li4")
return ret
上面的的脚本也可以通过如下执行:
redis-cli -p 6380 --eval redis_script.lua "my_string_key" "my_hash_key" , "zhang3" "li4"
案例2
if redis.call("EXISTS",KEYS[1]) == 1 then
return redis.call("INCR",KEYS[1])
else
return nil
end
19.2.3 执行SHA脚本
可以用SCRIPT LOAD指令 加载一个 lua脚本,得到SHA1编码。
redis-cli -p 6380 SCRIPT LOAD "$(cat redis_script.lua)"
$"b7e5a651ef461b2e0a98f7c83633816f1a0fb159"
然后通过得到的SHA执行脚本
redis-cli -p 6380 EVALSHA "b7e5a651ef461b2e0a98f7c83633816f1a0fb159" 2 my_string_key my_hash_key zhang3 li4