Jedis与Lua脚本结合
2、原子性的操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。因此在编写脚本的过程中无需担心会出现竞态条件,无需使用事务。
3、代码复用:客户端发送的脚步会永久存在redis中,这样,其他客户端可以复用这一脚本来完成相同的逻辑。
4、速度快:见 与其它语言的性能比较, 还有一个 JIT编译器可以显著地提高多数任务的性能; 对于那些仍然对性能不满意的人, 可以把关键部分使用C实现, 然后与其集成, 这样还可以享受其它方面的好处。
5、可以移植:只要是有ANSI C 编译器的平台都可以编译,你可以看到它可以在几乎所有的平台上运行:从 Windows 到Linux,同样Mac平台也没问题, 再到移动平台、游戏主机,甚至浏览器也可以完美使用 (翻译成JavaScript).
6、源码小巧:20000行C代码,可以编译进182K的可执行文件,加载快,运行快。
一般java运行lua脚本,采用的也是类似上述表达式,后面描述
(2)对于一段长的lua脚本,可以将脚本放在一个文件中,通过如下命令执行lua脚本
$ redis-cli --eval path/to/redis.lua KEYS[1] KEYS[2] , ARGV[1] ARGV[2] ...
--eval,告诉redis-cli读取并运行后面的lua脚本
path/to/redis.lua,是lua脚本的位置
KEYS[1] KEYS[2],是要操作的键,可以指定多个,在lua脚本中通过KEYS[1], KEYS[2]获取
ARGV[1] ARGV[2],参数,在lua脚本中通过ARGV[1], ARGV[2]获取。
注意: KEYS和ARGV中间的 ',' 两边的空格,不能省略。
看下面例子:
在如下文件夹中以一个lua脚本 jedisCallLuaTest.lua
local key=KEYS[1] local args=ARGV //说明:设置一个key = userName,value=Jack,20s过期时间 return redis.call("setex",key,unpack(args))
去客户端获取:
过期了。。。。
EVALSHA命令
将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。
语法如下:
redis 127.0.0.1:6379> EVALSHA sha1 numkeys key [key ...] arg [arg ...]
参数说明:
- sha1 : 通过 SCRIPT LOAD 生成的 sha1 校验码。
- numkeys: 用于指定键名参数的个数。
- key [key ...]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
- arg [arg ...]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。
eg:
整合Jedis + lua
(1)Jedis的使用
public class RedisClient {private static JedisPool jedisPool = null;private static String addr = "127.0.0.1";private static int port = 6379;static {try {JedisPoolConfig config = new JedisPoolConfig();// 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认trueconfig.setBlockWhenExhausted(true);// 设置的逐出策略类名, 默认DefaultEvictionPolicy(当连接超过最大空闲时间,或连接数超过最 大空闲连接数)config.setEvictionPolicyClassName("org.apache.commons.pool2.impl.DefaultEvictionPolicy");// 是否启用pool的jmx管理功能, 默认trueconfig.setJmxEnabled(true);// MBean ObjectName = new// ObjectName("org.apache.commons.pool2:type=GenericObjectPool,name="// + "pool" + i); 默认为"pool", JMX不熟,具体不知道是干啥的...默认就好.config.setJmxNamePrefix("pool");// 是否启用后进先出, 默认trueconfig.setLifo(true);// 最大空闲连接数, 默认8个 config.setMaxIdle(8);// 最大连接数, 默认8个config.setMaxTotal(8);// 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,// 默认-1config.setMaxWaitMillis(-1);// 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)config.setMinEvictableIdleTimeMillis(1800000);// 最小空闲连接数, 默认0config.setMinIdle(0);// 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3config.setNumTestsPerEvictionRun(3);// 对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数// 时直接逐出,不再根据MinEvictableIdleTimeMillis判断 (默认逐出策略)config.setSoftMinEvictableIdleTimeMillis(1800000);// 在获取连接的时候检查有效性, 默认falseconfig.setTestOnBorrow(false);// 在空闲时检查有效性, 默认falseconfig.setTestWhileIdle(false);// 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1config.setTimeBetweenEvictionRunsMillis(-1);jedisPool = new JedisPool(config, addr, port, 3000);} catch (Exception e) {e.printStackTrace();}}public synchronized static Jedis getJedis() {try {if (jedisPool != null) {Jedis resource = jedisPool.getResource();return resource;} else {return null;}} catch (Exception e) {e.printStackTrace();return null;}}public static void close(final Jedis jedis) {if (jedis != null) {jedis.close();}}/*---------------------测试---------------------------*/public static void main(java.lang.String[] args) {Jedis jedis = RedisClient.getJedis();// do something RedisClient.testCallLua(jedis);RedisClient.close(jedis);}public static void testCallLua(Jedis jedis){String luaStr = "return {KEYS[1],KEYS[1],ARGV[1],ARGV[2]}";Object result = jedis.eval(luaStr, Lists.newArrayList("userName","age"), Lists.newArrayList("Jack","20"));System.out.println(result);} }
运行结果:
[userName, userName, Jack, 20]
java: 该段代码图个方便,引用了guava.jar包
/*** 调用lua脚本* @param jedis*/public static void testCallLuaFile(Jedis jedis){String luaStr = null;//带反斜杠,路径为classPath,不带反斜杠,路径为类的同一目录Reader r = new InputStreamReader(RedisClient.class.getResourceAsStream("/jedisCallLuaTest.lua"));try {luaStr = CharStreams.toString(r);Object result = jedis.eval(luaStr, Lists.newArrayList("userName"), Lists.newArrayList("20","Tom"));System.out.println(result);} catch (IOException e) {e.printStackTrace();}}
注意:getResourceAsStream()这可是好帮手,用到将文件内容加载成String,一定要想到他。CharStreams是guava.jar中的对象。
Reader转String还有如下两种伎俩:(发散。。。。)
@Test public void apcheIo() throws IOException{String luaStr=null;//带反斜杠,路径为classPath,不带反斜杠,路径为类的同一目录Reader r= new InputStreamReader(Reader2StrDemo.class.getResourceAsStream("/jedisCallLuaTest.lua"));luaStr = org.apache.commons.io.IOUtils.toString(r);System.out.println(luaStr); }@Test public void java8() throws IOException{String luaStr=null;String path = "F:\\xxxx\\ideaProjects\\java8-pro\\resource\\jedisCallLuaTest.lua";luaStr = Files.lines(Paths.get(path),Charset.defaultCharset()).collect(Collectors.joining());System.out.println(luaStr); }
运行结果:
转载于:https://www.cnblogs.com/xiaozhuanfeng/p/10426501.html
Jedis与Lua脚本结合相关推荐
- Jedis使用lua脚本完成令牌桶限流
Jedis使用lua脚本完成令牌桶限流 文章目录 Jedis使用lua脚本完成令牌桶限流 一.lua脚本的简单语法 二.令牌桶限流 1. 构思 2. 实现 三.Jemeter压测工具测试 一.lua脚 ...
- Lua脚本语言快速入门手册
学了两天Lua语言,感叹其短小精悍,上手极快,语法还很舒服,不错!整理下学习过程中经常用到的基础知识,共勉! Lua用法简述 Lua语言是在1993年由巴西一个大学研究小组发明,其设计目标是作为嵌入式 ...
- Redis进阶-lua脚本
文章目录 Pre 语法 jedis操作lua 好处 lua实战 注意事项 Pre Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行. 语法 从Redis2.6.0 ...
- 高并发-【抢红包案例】之四:使用Redis+Lua脚本实现抢红包并异步持久化到数据库
文章目录 导读 概述 实现步骤 注解方式配置 Redis lua脚本和异步持久化功能的开发 Service层添加Redis抢红包的逻辑 Controller层新增路由方法 构造模拟数据,测试 代码 总 ...
- Redis:事务、管道、Lua脚本
1. Redis事务定义 Redis中的事务(transaction)是一组命令的集合.事务同命令一样都是Redis的最小执行单位,一个事务中的命令要么都执行,要么都不执行. 事务的原理是先将属于一个 ...
- springboot中使用lua脚本+aop作限流访问案例代码
文章目录 1.限流注解 2.redis配置 3.aop配置 4.controller层测试 拓展:Atomic类的学习 lua脚本学习 1.限流注解 @Target(ElementType.METHO ...
- Redis Lua脚本实现原子性操作
一.简介 redis操作时单线程的,平常如果想要redis原子性操作的话,可以使用incrBy()和decrBy()方法进行原子性的加减,但是对于事务性的逻辑操作,没有办法实现原子性,Redis 使用 ...
- lua脚本在redis集群中执行报错--Lua script attempted to access a non local key in a cluster node...
EVAL.EVALSHA命令 Redis从2.6.0版本开始提供了eval命令,通过内置的Lua解释器,可以让用户执行一段Lua脚本并返回数据.因为Redis单线程模型的特点,可以保证多个命令的原子性 ...
- Redis中的Lua 脚本
Lua/ˈluə/是一种轻量级脚本语言,它是用C 语言编写的,跟数据的存储过程有点类似.使用Lua 脚本来执行Redis 命令的好处: 1.一次发送多个命令,减少网络开销. 2.Redis 会将整个脚 ...
最新文章
- spring InitializingBean接口分析
- 使用火炬之光资源(转)
- 逻辑错误有哪些c语言,c语言程序,现在出现逻辑错误,哪位高手指点下啊。。。...
- 使用 Angular Universal 实现服务器端渲染
- 删除win10自带的软件
- uninitialized_copy测试代码示例
- websphere linux版本,安装IBM Websphere on linux
- FlinkCdc从Mysql指定的binlog日志offsetPos位置开始读取数据
- POJ1338 amp; POJ2545 amp; POJ2591 amp; POJ2247 找给定规律的数
- The proxy server is refusing connections 怎么解决呢?
- intel服务器最新主板芯片组,intel主板芯片组的介绍大全
- Git 连接码云 上传本地项目
- 11. 深度学习实践:实践方法论
- myanmar android2,Myanmar Thingyan Songs 2
- 关于RTL8192CU
- 线上实时监测推广效果,App投放渠道数据分析
- hbase region in transition
- 大厂面经系列 | 前端 | 美团,字节,京东,顺丰,携程 等题目分享
- 手把手教你,把3D模型从stl格式导出iges格式的方法
- JAVA IO中read()方法的返回值
热门文章
- 的级联选择_OpenCV-Python 级联分类器 | 六十二
- mysql8 create table 语法错误_MySQL8.0 Window Function 剖析
- Java实现穷举_LeetCode 28:实现strStr() Implement strStr()
- python写登录界面跳转至数据库操作_pycharm+jdango+python实现创建web工程并实现简单登陆...
- 大文件上传 之 改版了的SlickUpload.HttpUploadModule(Krystalware.SlickUpload.dll)
- win10 安装vue运行环境
- springboot怎么返回404_自定义SpringBoot REST API 404返回信息
- C语言:计算1!+2!+3!+...+100!
- java se 6 mac_Mac OS X “打开xx软件, 你需要一个Java SE 6运行环境”问题解决
- 缓冲池、顺序读取与随机读取