19.1 redis-lua 库

安装

  1. $ sudo luarocks install redis-lua

redis-lua 库 redis客户端端编程示例:

  1. local params = {
  2. host = '127.0.0.1',
  3. port = 6380,
  4. }
  5. local client = redis.connect(params)
  6. --string类型的操作
  7. client:set('foo', 'bar')
  8. local value = client:get('foo')
  9. print(value)
  10. --list操作
  11. client:lpush("lua_list_key", "123", "456")
  12. client:rpush("lua_list_key", "ABC")
  13. local list_array = client:lrange("lua_list_key", 0, -1)
  14. for key, val in pairs(list_array)
  15. do
  16. print("key = ", key)
  17. print("val = ", val)
  18. end
  19. --hash操作
  20. client:hset("lua_hash_key", "name", "zhang3")
  21. client:hset("lua_hash_key", "age", 18)
  22. local name = client:hget("lua_hash_key", "name")
  23. print("name = ".. name);
  24. local age = client:hget("lua_hash_key", "age")
  25. print("age = " .. age);
  26. local hash_zhang3 = client:hgetall("lua_hash_key")
  27. for key, val in pairs(hash_zhang3)
  28. do
  29. print("key = ", key)
  30. print("val = ", val)
  31. end
  32. --set 操作
  33. client:sadd("wbq_friends", "chenhe", "lichen", "marong", "dengchao")
  34. client:sadd("sz_friends", "sz_wife", "marong")
  35. local wbq_sz_friends = client:sinter("wbq_friends", "sz_friends")
  36. for key, val in pairs(wbq_sz_friends)
  37. do
  38. print("key = ", key)
  39. print("val = ", val)
  40. end
  41. --zset 操作
  42. client:zadd("music_top_zset", 98, "music01")
  43. client:zadd("music_top_zset", 91, "music02")
  44. client:zadd("music_top_zset", 97, "music03")
  45. local top_musics = client:zrange("music_top_zset", 0, -1)
  46. for key, val in pairs(top_musics)
  47. do
  48. print("key = ", key)
  49. print("val = ", val)
  50. end
  51. print("----- use withscores ----")
  52. local top_musics = client:zrange("music_top_zset", 0, -1, {withscores=true})
  53. for key, val in pairs(top_musics)
  54. do
  55. print("key = ", key)
  56. for index, value in pairs(val)
  57. do
  58. if (index == 1) then
  59. print("member = ", value)
  60. end
  61. if (index == 2) then
  62. print("socre = ", value)
  63. end
  64. end
  65. end
  66. --key 操作
  67. client:del("foo")
  68. client:del("lua_list_key")
  69. client:del("wbq_friends")
  70. client:del("sz_friends")
  71. client:del("music_top_zset")

19.2 redis 嵌入lua脚本

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

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

19.2.1 redis直接执行lua脚本文件

  1. local msg = "hello lua in redis"
  2. return msg

这是非常简单的,第一行代码定义了一个本地变量msg存储我们的信息, 第二行代码表示 从redis 服务端返回msg的值给客户端。 保存这个文件到hello_redis.lua,像这样去运行:local msg = “hello lua in redis”

  1. 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存储于一个哈希中的键值:

  1. local ret = redis.call("SET", KEYS[1], ARGV[1])
  2. redis.call("HSET", KEYS[2], "name", ARGV[2])
  3. return ret

把以上代码保存为文件“redis_script.lua”中。

执行:

  1. 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的个数,除非传入的完全是命令。

以上指令相当于脚本

  1. local ret = redis.call("SET", "my_string_key", "zhang3")
  2. redis.call("HSET", "my_hash_key", "name", "li4")
  3. return ret

上面的的脚本也可以通过如下执行:

  1. redis-cli -p 6380 --eval redis_script.lua "my_string_key" "my_hash_key" , "zhang3" "li4"

案例2

  1. if redis.call("EXISTS",KEYS[1]) == 1 then
  2. return redis.call("INCR",KEYS[1])
  3. else
  4. return nil
  5. end

19.2.3 执行SHA脚本

可以用SCRIPT LOAD指令 加载一个 lua脚本,得到SHA1编码。

  1. redis-cli -p 6380 SCRIPT LOAD "$(cat redis_script.lua)"
  2. $"b7e5a651ef461b2e0a98f7c83633816f1a0fb159"

然后通过得到的SHA执行脚本

  1. redis-cli -p 6380 EVALSHA "b7e5a651ef461b2e0a98f7c83633816f1a0fb159" 2 my_string_key my_hash_key zhang3 li4