🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 19 Lua 与 redis ## 1 redis-lua 库 ### 安装 ```lua $ sudo luarocks install redis-lua ``` ### redis-lua 库 redis客户端端编程示例: ```lua 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 脚本的两个命令 ——[EVAL](http://redis.readthedocs.org/en/latest/script/eval.html#eval)和[EVALSHA](http://redis.readthedocs.org/en/latest/script/evalsha.html#evalsha)的实现原理进行介绍。 ### 2.1 redis直接执行lua脚本文件 ```lua local msg = "hello lua in redis" return msg ``` 这是非常简单的,第一行代码定义了一个本地变量msg存储我们的信息, 第二行代码表示 从redis 服务端返回msg的值给客户端。 保存这个文件到hello\_redis.lua,像这样去运行:local msg = "hello lua in redis" ```lua 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存储于一个哈希中的键值: ```lua local ret = redis.call("SET", KEYS[1], ARGV[1]) redis.call("HSET", KEYS[2], "name", ARGV[2]) return ret ``` 把以上代码保存为文件“redis\_script.lua"中。 执行: ```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的个数,除非传入的完全是命令。 以上指令相当于脚本 ```lua local ret = redis.call("SET", "my_string_key", "zhang3") redis.call("HSET", "my_hash_key", "name", "li4") return ret ``` 上面的的脚本也可以通过如下执行: ```lua redis-cli -p 6380 --eval redis_script.lua "my_string_key" "my_hash_key" , "zhang3" "li4" ``` > 案例2 ```lua 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编码。 ```lua redis-cli -p 6380 SCRIPT LOAD "$(cat redis_script.lua)" $"b7e5a651ef461b2e0a98f7c83633816f1a0fb159" ``` 然后通过得到的SHA执行脚本 ```lua redis-cli -p 6380 EVALSHA "b7e5a651ef461b2e0a98f7c83633816f1a0fb159" 2 my_string_key my_hash_key zhang3 li4 ```