Redis中使用Lua语言

在 Redis 的 2.6 以上版本中,除了可以使用命令外,还可以使用 Lua 语言操作 Redis。从前面的命令可以看出 Redis 命令的计算能力并不算很强大,而使用 Lua 语言则在很大程度上弥补了 Redis 的这个不足。

只是在 Redis 中,执行 Lua 语言是原子性的,也就说 Redis 执行 Lua 的时候是不会被中断的,具备原子性,这个特性有助于 Redis 对并发数据一致性的支持。

Redis 支持两种方法运行脚本,一种是直接输入一些 Lua 语言的程序代码;另外一种是将 Lua 语言编写成文件。

在实际应用中,一些简单的脚本可以采取第一种方式,对于有一定逻辑的一般采用第二种方式。而对于采用简单脚本的,Redis 支持缓存脚本,只是它会使用 SHA-1 算法对脚本进行签名,然后把 SHA-1 标识返回回来,只要通过这个标识运行就可以了。

执行输入 Lua 程序代码

它的命令格式为:

eval lua-script key-num [key1 key2 key3 ...] [value1 value2 value3 ...]

解说:

	eval 代表执行 Lua 语言的命令。
	
	Lua-script 代表 Lua 语言脚本。
	
	key-num 整数代表参数中有多少个 key,需要注意的是 Redis 中 key 是从 1 开始的,如果没有 key 的参数,那么写 0。
	
	[key1key2key3...] 是 key 作为参数传递给 Lua 语言,也可以不填它是 key 的参数,但是需要和 key-num 的个数对应起来。
	
	[value1 value2 value3...] 这些参数传递给 Lua 语言,它们是可填可不填的。

这里难理解的是 key-num 的意义,举例说明。
在这里插入图片描述

可以看到执行了两个 Lua 脚本。

eval "return'hello java'" 0

这个脚本只是返回一个字符串,并不需要任何参数,所以 key-num 填写了 0,代表着没有任何 key 参数。按照脚本的结果就是返回了 hello java,所以执行后 Redis 也是这样返回的。这个例子很简单,只是返回一个字符串。

eval "redis.call('set',KEYS[1],ARGV[1])" 1 lua-key lua-value

设置一个键值对,可以在 Lua 语言中采用 redis.call(command,key[param1,param2…]) 进行操作,其中:

	command 是命令,包括 set、get、del 等。
	
	Key 是被操作的键。
	
	param1,param2...代表给 key 的参数。

脚本中的 KEYS[1] 代表读取传递给 Lua 脚本的第一个 key 参数,而 ARGV[1] 代表第一个非 key 参数。

这里共有一个 key 参数,所以填写的 key-num 为 1,这样 Redis 就知道 key-value 是 key 参数,而 lua-value 是其他参数,它起到的是一种间隔的作用。

最后我们可以看到使用 get 命令获取数据是成功的,所以 Lua 脚本运行成功了。

有时可能需要多次执行同样一段脚本,这个时候可以使用 Redis 缓存脚本的功能,在 Redis 中脚本会通过 SHA-1 签名算法加密脚本,然后返回一个标识字符串,可以通过这个字符串执行加密后的脚本。

这样的一个好处在于,如果脚本很长,从客户端传输可能需要很长的时间,那么使用标识字符串,则只需要传递 32 位字符串即可,这样就能提高传输的效率,从而提高性能。

首先使用命令:

script load script

这个脚本的返回值是一个 SHA-1 签名过后的标识字符串,我们把它记为 shastring。通过 shastring 可以使用命令执行签名后的脚本,命令的格式是:

evalsha shastring keynum [key1 key2 key3 ...] [param1 param2 param3 ...]

下面演示过程。
在这里插入图片描述

对脚本签名后就可以使用 SHA-1 签名标识运行脚本了。在 Spring 中演示这样的一个过程,如果是简单存储,笔者认为原来的 API 中的 Jedis 对象就简单些,所以先获取了原来的 connection 对象,代码如下所示。

// 如果是简单的对象,使用原来的封装会简易些
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
        "applicationContext.xml");
RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
applicationContext.getBean(RedisTemplate.class);
// 如果是简单的操作,使用原来的Jedis会简易些
Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
// 执行简单的脚本
String helloJava = (String) jedis.eval("return 'hello java'"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值