lua官网:https://www.lua.org/
file-New Project
1)下载
https://github.com/rjpcomputing/luaforwindows/releases
2)安装
直接按照就好
3)配置Debug
program选择lua安装路径
代码
local function main()
print("hello world")
end
main()
执行
and break do else elseif end false for function if in local nil not or repeat return then true until while
-- 两个减号是行注释
--[[
这是块注释
这是块注释.
--]]
Lua的数字只有double型,64bits
你可以以如下的方式表示数字
num = 1024
num = 3.0
num = 3.1416
num = 314.16e-2
num = 0.31416E1
num = 0xff
num = 0x56
可以用单引号,也可以用双引号
也可以使用转义字符‘\n’ (换行), ‘\r’ (回车), ‘\t’ (横向制表), ‘\v’ (纵向制表), ‘\’ (反斜杠), ‘\”‘ (双引号), 以及 ‘\” (单引号)等等
下面的四种方式定义了完全相同的字符串(其中的两个中括号可以用于定义有换行的字符串)
a = 'alo\n123"'
a = "alo\n123\""
a = '\97lo\10\04923"'
a = [[alo
123"]]
C语言中的NULL在Lua中是nil,比如你访问一个没有声明过的变量,就是nil
只有nil和false是 false
数字0,‘’空字符串(’\0’)都是true
lua中的变量如果没有特殊说明,全是全局变量,那怕是语句块或是函数里。
变量前加local关键字的是局部变量
local i = 0
local max = 10
while i <= max do
print(i)
i = i +1
end
local function main()
local age = 140
local sex = 'Male'
if age == 40 and sex =="Male" then
print(" 男人四十一枝花 ")
elseif age > 60 and sex ~="Female" then
print("old man without country!")
elseif age < 20 then
io.write("too young, too naive!\n")
else
print("Your age is "..age)
end
end
-- 调用
main()
sum = 0
for i = 100, 1, -2 do
sum = sum + i
end
function myPower(x,y)
return y+x
end
power2 = myPower(2,3)
print(power2)
function newCounter()
local i = 0
return function() -- anonymous function
i = i + 1
return i
end
end
c1 = newCounter()
print(c1()) --> 1
print(c1()) --> 2
print(c1())
name, age,bGay = "yiming", 37, false, "yimingl@hotmail.com"
print(name,age,bGay)
function isMyGirl(name)
return name == 'xiao6' , name
end
local bol,name = isMyGirl('xiao6')
print(name,bol)
key,value的键值对 类似 map
lucy = {name='xiao6',age=18,height=165.5}
xiao6.age=35
print(xiao6.name,xiao6.age,xiao6.height)
print(xiao6)
arr = {"string", 100, "xiao6",function() print("memeda") return 1 end}
print(arr[4]())
遍历
for k, v in pairs(arr) do
print(k, v)
end
person = {name='xiao6',age = 18}
function person.eat(food)
print(person.name .." eating "..food)
end
person.eat("xxoo")
从redis2.6.0版本开始,通过内置的lua编译器和解析器,可以使用eval命令执行lua脚本
登录到客户端后执行
eval "return 1+1" 0
#命令 脚本 参数个数
EVAL "local msg='hello world' return msg..KEYS[1]" 1 AAA BBB
#…表示拼接字符串
表是基于1的,也就是说索引以数值1开始。所以在表中的第一个元素就是mytable[1],第二个就是mytable[2]等等。
表中不能有nil值。如果一个操作表中有[1, nil, 3, 4],那么结果将会是[1]——表将会在第一个nil截断
1)创建一个脚本
local list=redis.call("get","qq");
return list;
2)执行脚本
redis-cli -p 6379 -a 573875306 --eval /usr/local/programs/redis-5.0.10/mylua/test.lua 0
3)带参数
test.lua
local num = redis.call('get',KEYS[1]);
if not num then
return num;
else
local res = num * KEYS[2] * ARGV[1];
redis.call('set',KEYS[1],res);
return res;
end;
执行
这里要说明一下linux中执行lua脚本参数传值和redis命令执行lua脚本传值的差异问题。
如果传入多个参数,那么在redis命令中,需要指定key的个数,所有的key和argv参数之间都使用空格分隔即可,lua脚本执行时,会根据传入的key个数自动区分开key参数和argv参数;
但是在linux命令中,key参数和argv参数要用逗号分隔,key和key之间、argv与argv之间用空格分隔,如果key和argv之间不使用逗号,则会抛出异常,并且逗号前后需有空格,否则会被认为是传的一个参数,同样会抛出异常
redis-cli -p 6379 -a 573875306 --eval /usr/local/programs/redis-5.0.10/mylua/test.lua launumber 20 , 30
通过 Lua 脚本的全局变量 KEYS 和 ARGV,能够访问 EVAL 和 EVALSHA 命令的 key [key …] 参数和 arg [arg …] 参数。
作为 Lua Table,能够将 KEYS 和 ARGV 作为一维数组使用,其下标从 1 开始。
Lua 脚本内部允许通过内置函数执行 Redis 命令:
redis.call()
redis.pcall()
两者非常相似,区别在于:
若 Redis 命令执行错误,redis.call() 将错误抛出(即 EVAL & EVALSHA 执行出错);
redis.pcall() 将错误内容返回。
local msg='count:' local count = redis.call("get","count") if not count then redis.call("set","count",1) end redis.call("incr","count") return msg..count+1
redis 原生支持 监听、事务、批处理,那么还需要lua吗?
两者不存在竞争关系,而是增强关系,lua可以完成redis自身没有的功能
在lua中可以使用上一步的结果,也就是可以开发后面操作依赖前面操作的执行结果的应用,MULT中的命令都是独立操作
redis可以编写模块增强功能,但是c语言写模块,太难了,lua简单的多
计算向移动数据
原子操作
lua脚本尽量短小并且尽量保证同一事物写在一段脚本内,因为redis是单线程的,过长的执行会造成阻塞,影响服务器性能。
1)script load 此命令用于将Lua脚本加载到Redis内存中
2)script exists scripts exists sha1 [sha1 …] 此命令用于判断sha1是否已经加载到Redis内存中
3)script flush 此命令用于清除Redis内存已经加载的所有Lua脚本,在执行script flush后,sha1不复存在
4)script kill 此命令用于杀掉正在执行的Lua脚本
下面代码会进入死循环,导致redis无法接受其他命令。
eval "while true do end" 0
127.0.0.1:6379> keys *
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
但是可以接受 SCRIPT KILL or SHUTDOWN NOSAVE. 两个命令
SHUTDOWN NOSAVE 不会进行持久化的操作
SCRIPT KILL 可以杀死正在执行的进程
redis-cli script load "$(cat test.lua)"
得到sha1值
执行
redis-cli evalsha "7a2054836e94e19da22c13f160bd987fbc9ef146" 0
我们都知道Nginx有很多的特性和好处,但是在Nginx上开发成了一个难题,Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开发者对其望而生畏。为了开发人员方便,所以接下来我们要介绍一种整合了Nginx和lua的框架,那就是OpenResty,它帮我们实现了可以用lua的规范开发,实现各种业务,并且帮我们弄清楚各个模块的编译顺序。关于OpenResty,我想大家应该不再陌生,随着系统架构的不断升级、优化,OpenResty在被广泛的应用
http://openresty.org/cn/download.html
官方文档安装介绍:http://openresty.org/cn/installation.html
1)下载好的文件
2)上传到服务器解压
tar -xzvf xxx
3)进入目录/usr/local/openresty-1.21.4.1
4)环境准备
yum install pcre-devel openssl-devel gcc curl -y
5)安装perl
https://www.cnblogs.com/jthr/p/16911499.html
6)执行
./configure
7) 安装
程序会被安装到`/usr/local/openresty`目录
make
make install
8) 启动
./nginx -c /usr/local/openresty/nginx//conf/nginx.conf
9)访问
4.3.1 服务命令
1)启动
Service openresty start
2)停止
Service openresty stop
3)检查配置文件是否正确
Nginx -t
4)重新加载配置文件
Service openresty reload
5)查看已安装模块和版本号
Nginx -V
1)进入目录
这里进入的是openresty下的nginx目录,这就是一个全新的可以使用lua扩展的nginx
2)修改配置文件nginx.conf
/usr/local/openresty/nginx/conf
首先修改下端口号,免得冲突:server下的 listen属性
listen 8099;
在server下添加一个local
location /lua {
default_type text/html;
content_by_lua_file /usr/local/openresty/nginx/lua/hello.lua; #也可以用相对路径,相对目录在nginx下
}
3)进入上面配置的目录,创建hello.lua
添加内容
ngx.say("
Hello, World!
")4)重新启动
./nginx -s stop
./nginx -c /usr/local/openresty/nginx//conf/nginx.conf
5)访问
http://192.168.28.110:8099/lua
如果出错,可以在/usr/local/openresty/nginx/logs下查看日志查找原因
没有配置热部署,修改hello.lua,都需要重新启动
修改配置文件:/usr/local/openresty/nginx/conf/nginx.conf
在http下加上配置:lua_code_cache off; #热部署,每次执行都编译
重新启动,再修改hello.lua直接刷新页面就可以
1)获取Nginx请求头信息
local headers = ngx.req.get_headers()
ngx.say("Host : ", headers["Host"], "
")
ngx.say("user-agent : ", headers["user-agent"], "
")
ngx.say("user-agent : ", headers.user_agent, "
")
for k,v in pairs(headers) do
if type(v) == "table" then
ngx.say(k, " : ", table.concat(v, ","), "<br/>")
else
ngx.say(k, " : ", v, "<br/>")
end
end
2)获取post请求参数
ngx.req.read_body()
ngx.say("post args begin", "
")
local post_args = ngx.req.get_post_args()
for k, v in pairs(post_args) do
if type(v) == "table" then
ngx.say(k, " : ", table.concat(v, ", "), "<br/>")
else
ngx.say(k, ": ", v, "<br/>")
end
end
3)获取http协议版本
ngx.say("ngx.req.http_version : ", ngx.req.http_version(), "
")
4)获取请求方法
ngx.say("ngx.req.get_method : ", ngx.req.get_method(), "
")
5)获取原始的请求头内容
ngx.say("ngx.req.raw_header : ", ngx.req.raw_header(), "
")
6)获取body内容体
ngx.say("ngx.req.get_body_data() : ", ngx.req.get_body_data(), "
")
多进程共享,且能保障原子性。可以通过lua去访问它。
重载Nginx配置时,缓存数据会丢失。
1)修改配置文件:/usr/local/openresty/nginx/conf/nginx.conf
在http下加上一行配置
lua_shared_dict shared_data 1m;
重新启动
2)修改hello.lua
local shared_data = ngx.shared.shared_data
local i = shared_data:get("i")
if not i then
i = 1
shared\_data:set("i", i)
ngx.say("lazy set i ", i, "<br/>")
end
i = shared_data:incr("i", 1)
ngx.say("i=", i, "
")
3)访问
gihub地址:https://github.com/openresty/lua-resty-lrucache
Lua 实现的一个简单的 LRU 缓存,适合在 Lua 空间里直接缓存较为复杂的 Lua 数据结构
它相比 ngx_lua 共享内存字典可以省去较昂贵的序列化操作,相比 memcached 这样的外部服务又能省去较昂贵的 socket 操作
1)支持更丰富的数据类型,可以把table存放在value中,这对数据结构复杂的业务非常有用。
2)可以预先分配key的数量,不用设置固定的内存空间,在内存的使用上更为灵活。
3)每个worker进程独立缓存,所以当worker进程同时读取同一个key 时不存在锁竞争。
但它与lua_shared_dict相比也有一些缺点
1)因为数据不在worker之间共享,所以无法保证在更新数据时,数据在同一时间的不同worker进程上完全一致。
2)虽然可以支持复杂的数据结构,但可使用的指令却很少,如不支持消息队列功能。
3)重载Nginx配置时,缓存数据会丢失。如果使用lua_shared_dict,则不会如此
1)修改配置文件:/usr/local/openresty/nginx/conf/nginx.conf
注释掉热部署,每次都编译对缓存会造成影响,使用不正确
#lua_code_cache off; #热部署,每次执行都编译
之前配置的location 进行修改
location /lua {
default_type text/html;
content_by_lua_block {
require("my/cache").go()
}
}
2)编码
在/usr/local/openresty/lualib创建文件夹my(因为上面配置的相对路径,它会在这些目录下去找)
在my下创建文件cache.lua
写入内容
local _M = {}
lrucache = require "resty.lrucache"
c, err = lrucache.new(200) -- allow up to 200 items in the cache
ngx.say("count=init")
if not c then
error("failed to create the cache: " .. (err or "unknown"))
end
function _M.go()
count = c:get("count")
c:set("count",100)
ngx.say("count=", count, " --
")
if not count then
c:set("count",1)
ngx.say("lazy set count ", c:get("count"), "<br/>")
else
c:set("count",count+1)
ngx.say("count=", count, "
")
end
end
return _M
3)重启
4)访问
手机扫一扫
移动阅读更方便
你可能感兴趣的文章