19 Lua 与 redis

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")

2 redis 嵌入lua脚本

Lua 脚本功能是 Reids 2.6 版本的最大亮点, 通过内嵌对 Lua 环境的支持, Redis 解决了长久以来不能高效地处理 CAS (check-and-set)命令的缺点, 并且可以通过组合使用多个命令, 轻松实现以前很难实现或者不能高效实现的模式。

本章先介绍 Lua 环境的初始化步骤, 然后对 Lua 脚本的安全性问题、以及解决这些问题的方法进行说明, 最后对执行 Lua 脚本的两个命令 ——EVALEVALSHA的实现原理进行介绍。

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.

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

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

results matching ""

    No results matching ""