redis入门指南-脚本

前言

redis在2.6之后推出了脚本功能. 允许开发者使用lua语言编写的脚本上传到redis中运行.在执行的过程中可以调用大部分的redis命令.

好处

使用脚本的好处:

  1. 减少网络开销:
    如果按照我们正常编写客户端代码, 比如py, 执行的时候就是向redis服务发送了多次请求命令, 但是如果使用脚本, 就只需要发送一次请求就好了, 减少网络延迟
  2. 原子操作:
    redis会将整个脚本作为一个整体执行. 中间不会被别的命令插入, 所以无需使用事务.
  3. 复用:
    客户端发送的脚本会永久的存在redis中, 所以可以被复用(其他语言也可以)

lua脚本

lua是一个高效的轻量级脚本语言. 能方便的嵌入到其他的语言这种

lua的特性

  1. 轻量级:
    标准c编写, 并以源代码形式开放. 编辑后仅仅一百余K, 方便嵌入到其他的程序中
  2. 可扩展:
    Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
  3. 其他:
  • 支持面向过程(procedure-oriented)编程和函数式编程(functional programming);
  • 自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象;
  • 语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持;
  • 通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等。

lua应用场景

  1. 游戏开发
  2. 独立应用脚本
  3. web应用脚本
  4. 扩展和数据库插件
  5. 安全系统

语法

数据类型

lua是动态类型语言, 和Python一样

变量

lua变量分为全局变量和局部变量. 全局变量不需要声明就可以直接使用, 默认值是nil

1
2
3
a = 1 # 全局变量a赋值
print (b) # 无需声明就可以使用, 打印nil
a = nil # 删除全局变量就是将其赋值为nil

在redis中不允许使用全局变量, 只允许使用局部变量防止脚本之间的互相影响
局部变量使用local声明:

1
2
3
local c
local d = 1
local e, f

声明一个局部函数:

1
2
3
local say_ho = function()
print 'hi'
end

局部函数的作用域从声明的时候开始到所在层的语句块末尾, 比如:

1
2
3
4
5
6
7
8
9
10
11
local x = 10
if true then:
local x = x + 1
print(x)
do
local x = x +1
print(x)
end
print(x)
end
print(x)

结果是这样的:

1
2
3
4
11
12
11
10

注释

单行: –
多行: –[[开始, 到]]结束

赋值

可以多重赋值

操作符

if语句


注意: 只有遇到nil和false才是假

循环

支持 while, repeat, for

  1. while

    1
    2
    3
    while (条件) do
    语句块
    do
  2. repeat

    1
    2
    3
    repeat
    语句块
    until 条件表达式
  3. for

    1
    2
    3
    for 变量=初值, 终值, 步长 do
    语句块
    end

步长可以省略

表类型

表是lua中唯一的数据结构
其实就可以理解为python中的dict或者java中的map

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
--[[ 函数返回两个值的最大值 --]]
function max(num1, num2)

if (num1 > num2) then
result = num1;
else
result = num2;
end

return result;
end
-- 调用函数
print("两值比较最大值为 ",max(10,4))
print("两值比较最大值为 ",max(5,6))

标准库

lua标准库提供了一些实用的函数

redis和lua

编写redis脚本的目的就是读写数据库

在脚本中调用redis命令

1
2
redis.call('set', 'foo', 'bar')
local value = redis.call('get', 'foo')

从脚本中返回

多数情况需要lua有返回值, 如果没有返回值, 则是nil

脚本相关命令

  1. eval
    编写完脚本之后最重要的就是执行脚本, redis提供了eval命令可以使开发者像调用其他redis内置命令一样调用脚本.
    格式是:
    eval 脚本内容 key参数的数量 [key …] [arg …]
    可以通过key和arg这两个参数向脚本传递数据, 比如我们实现SET命令
    1
    return redis.call('SET', KEYS[1], ARGV[1])

现在redis-cli中调用
eval “return redis.call(‘SET’, KEYS[1], ARGV[1])” 1 foo bar

  1. evalsha
    考虑在脚本如果比较长的情况下, 如果每次把脚本传给redis, 比较占用带宽. redis提供了evalsha命令允许开发者通过脚本内容的SHA1摘要来执行脚本