初探Lua脚本
创始人
2024-05-03 06:23:45
0

1、什么是Lua

  Lua脚本是一个由C语言编写的小巧脚本语言,在所有脚本引擎中,Lua的速度是最快的。Lua的核心代码不过一万多行,因为是C语言编写的,因此Lua可以在几乎所有的操作系统和平台进行编译运行

2、Lua适用场景

1)、辑相对简单,没有复杂的数据交互,访问频次超高的接口实现

2)、 lua适合的是无阻塞的,如果脚本含有文件读写,也快不到哪去

常见搭配:

Nginx + lua 开发高性能web应用,限流、防止sql注入、请求过滤,黑白名单限制等等等。

redis + lua  实现原子操作,避免多线程数据不一致的问题

3、Lua安装以及基本语法

1)Lua安装教程

2)Lua基本语法

学过java的人,看Lua脚本应该也是手到擒来,这里就不展开讲了。

4、Redis中使用Lua

Redis 2.6 版本之后才通过内嵌支持 Lua 环境,在Redis中通过Lua脚本可以实现原子操作,因为Redis服务端会将Lua脚本当作一条命令去执行,同时如果程序中存在多次Redis交互的场景,也可以通过讲这些命令合并写到一个脚本中,这些减少了网络交互次数,也间接的提升了性能,不过也要保证脚本不要太大,过于复杂。

核心命令:EVAL

EVAL script numkeys key [key …] arg [arg …]
  • script:lua脚本程序
  • numkeys:  用于指定键名参数的个数
  • key [key...]:从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
  • arg [arg ...]:附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。

比如说执行这样一个命令

EVAL "local num = 1; redis.call('set',KEYS[1],ARGV[1] + num) return redis.call('get',KEYS[1])" 1 testKey 10

其中script参数对应的脚本如下 

numkeys的参数对应1,表示后面有几个key

key的参数对应testKey,只有一个key

arg参数对应10,也就是这个key对应的value

这条命令的意思就是定义了一个num,然后往里面set进了一个值,KEYS[1] 也就是传入的参数key,ARGV[1]也就是传入的value,然后进行相加,最后脚本返回相加的一个结果为11。

这样就将原本两个命令先set,再get替换成了一个原子命令去执行。

这里再以Redission作为客户端演示一下,代码里面如何去执行:

	public static void main(String[] args) throws Exception{Config config = new Config();config.useSingleServer().setAddress("redis://localhost:6379");config.useSingleServer().setPassword("123456");RedissonClient client = Redisson.create(config);RScript rScript = client.getScript();String script = "local num = 1;" +"redis.call('set',KEYS[1],ARGV[1] + num);" +"return redis.call('get',KEYS[1])";Integer value = rScript.eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE, Collections.singletonList("key"), 10);System.out.println("直接执行脚本:"+value);}

 在调用api的时候,大家可能会发现eval和evalsha这两个api,其实这两个都是用来执行lua脚本的。但是eval命令是直接发送lua脚本的,而evalsha是发送一个之前执行过的lua脚本的,使用evalsha命令可以减少lua脚本网络发送的开销,不过要注意的是,在使用evalsha这个命令时,要先把脚本 预加载到Redis服务器上,例如这样:

		String script = "local num = redis.call('get',KEYS[1]);" +"redis.call('set',KEYS[1],ARGV[1] + num);" +"return redis.call('get',KEYS[1])";// 预加载脚本String shaDigest = rScript.scriptLoad(script);Integer value2 = rScript.evalSha(RScript.Mode.READ_WRITE, shaDigest, RScript.ReturnType.VALUE, Collections.singletonList("key"), 10);System.out.println("执行缓存脚本:"+value2);

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...