文档章节

redis调用lua脚本注意事项

r
 rui1993
发布于 2017/03/24 17:52
字数 1513
阅读 504
收藏 1

使用脚本的好处:

  • 减少网络开销。可以将多个请求通过脚本的形式一次发送,减少网络时延
  • 原子操作。redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。因此在编写脚本的过程中无需担心会出现竞态条件,无需使用事务。
  • 复用。客户端发送的脚步会永久存在redis中,这样,其他客户端可以复用这一脚本而不需要使用代码完成相同的逻辑。

调用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中间的 ',' 两边的空格,不能省略。

redis支持大部分Lua标准库

库名 说明
Base 提供一些基础函数
String 提供用于字符串操作的函数
Table 提供用于表操作的函数
Math 提供数学计算函数
Debug 提供用于调试的函数

在脚本中调用redis命令

在脚本中可以使用redis.call函数调用Redis命令

redis.call('set', 'foo', 'bar')
local value=redis.call('get', 'foo') --value的值为bar

redis.call函数的返回值就是Redis命令的执行结果

Redis命令的返回值有5种类型,redis.call函数会将这5种类型的回复转换成对应的Lua的数据类型,具体的对应规则如下(空结果比较特殊,其对应Lua的false)

redis返回值类型和Lua数据类型转换规则

redis返回值类型 Lua数据类型
整数回复 数字类型
字符串回复 字符串类型
多行字符串回复 table类型(数组形式)
状态回复 table类型(只有一个ok字段存储状态信息)
错误回复 table类型(只有一个err字段存储错误信息)

redis还提供了redis.pcall函数,功能与redis.call相同,唯一的区别是当命令执行出错时,redis.pcall会记录错误并继续执行,而redis.call会直接返回错误,不会继续执行。

在脚本中可以使用return语句将值返回给客户端,如果没有执行return语句则默认返回nil

Lua数据类型和redis返回值类型转换规则

Lua数据类型 redis返回值类型
数字类型 整数回复(Lua的数字类型会被自动转换成整数)
字符串类型 字符串回复
table类型(数组形式) 多行字符串回复
table类型(只有一个ok字段存储状态信息) 状态回复
table类型(只有一个err字段存储错误信息) 错误回复

脚本相关命令

  1. EVAL "lua-script" [key ...] [arg ...]

    通过key和arg这两类参数向脚本传递数据,它们的值在脚本中分别使用KEYS和ARGV两个表类型的全局变量访问。

    注意: EVAL命令依据参数key-number来将其后面的所有参数分别存入脚本中KEYS和ARGV两个table类型的全局变量。当脚本不需要任何参数时,也不能省略这个参数(设为0)

    redis>EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 foo bar
    OK
    redis>GET foo
    "bar"
  2. EVALSHA命令

    在脚本比较长的情况下,如果每次调用脚本都需要将整个脚本传给Redis会占用较多的带宽。为了解决这个问题,Redis提供了EVALSHA命令,允许开发者通过脚本内容的SHA1摘要来执行脚本,该命令的用法和EVAL一样,只不过是将脚本内容替换成脚本内容的SHA1摘要。

    Redis在执行EVAL命令时会计算脚本的SHA1摘要并记录在脚本缓存中,执行EVALSHA命令时Redis会根据提供的摘要从脚本缓存中查找对应的脚本内容,如果找到了则执行脚本,否则会返回错误:"NOSCRIPT No matching script. Please use EVAL."

    在程序中使用EVALSHA命令的一般流程如下。

    1. 先计算脚本的SHA1摘要,并使用EVALSHA命令执行脚本。
    2. 获得返回值,如果返回“NOSCRIPT”错误则使用EVAL命令重新执行脚本。

    虽然这一流程略显麻烦,但值得庆幸的是很多编程语言的Redis客户端都会代替开发者完成这一流程。执行EVAL命令时,先尝试执行EVALSHA命令,如果失败了才会执行EVAL命令。

  3. SCRIPTLOAD "lua-script"

    将脚本加入缓存,但不执行. 返回:脚本的SHA1摘要

  4. SCRIPT EXISTS lua-script-sha1

    判断脚本是否已被缓存

  5. SCRIPT FLUSH

    清空脚本缓存 redis将脚本的SHA1摘要加入到脚本缓存后会永久保留,不会删除,但可以手动使用SCRIPT FLUSH命令情况脚本缓存。

  6. SCRIPT KILL

    强制终止当前脚本的执行。 但是,如果当前执行的脚步对redis的数据进行了写操作,则SCRIPT KILL命令不会终止脚本的运行,以防止脚本只执行了一部分。脚本中的所有命令,要么都执行,要么都不执行。

Redis的脚本执行是原子的,即脚本执行期间Redis不会执行其他命令。所有的命令都必须等待脚本执行完成后才能执行。为了防止某个脚本执行时间过长导致Redis无法提供服务(比如陷入死循环),Redis提供了lua-time-limit参数限制脚本的最长运行时间,默认为5秒钟。当脚本运行时间超过这一限制后,Redis将开始接受其他命令但不会执行(以确保脚本的原子性,因为此时脚本并没有被终止),而是会返回“BUSY”错误

本文转载自:http://blog.csdn.net/wzzfeitian/article/details/42081837

r
粉丝 2
博文 14
码字总数 2206
作品 0
深圳
私信 提问
Redis分布式缓存系统Lua脚本食用指引

Redis 为什么添加 Lua 支持 redis lua 脚本出现之前 Redis 是没有服务器端运算能力的,主要是用来存储,用做缓存,运算是在客户端进行,这里有两个缺点:一、如此会破坏数据的一致性,试想如...

斯武丶风晴
2016/06/15
184
0
Redis进阶实践之十九 Redis如何使用lua脚本

Redis进阶实践之十九 Redis如何使用lua脚本 一、引言 redis学了一段时间了,基本的东西都没问题了。从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何...

morpheusWB
2018/09/13
77
0
Lua: 给 Redis 用户的入门指导

可能你已经听说过Redis 中嵌入了脚本语言,但是你还没有亲自去尝试吧? 这个入门教程会让你学会在你的Redis 服务器上使用强大的lua语言。 Hello, Lua! 我们的第一个Redis Lua 脚本仅仅返回一...

ifsc01
2013/03/19
44.9K
12
如何优雅地在Redis中使用Lua

作者:可均可可 原文:http://www.cnblogs.com/PatrickLiu/p/8391829.html 一、引言 今天讲一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何平台上,也可以嵌入到大...

程序员之家_
02/08
0
0
Redis进阶实践之七Redis和Lua初步整合使用

Redis进阶实践之七Redis和Lua初步整合使用 一、引言 Redis学了一段时间了,基本的东西都没问题了。从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何...

morpheusWB
2018/09/13
31
2

没有更多内容

加载失败,请刷新页面

加载更多

Mybatis Plus删除

/** @author beth @data 2019-10-17 00:30 */ @RunWith(SpringRunner.class) @SpringBootTest public class DeleteTest { @Autowired private UserInfoMapper userInfoMapper; /** 根据id删除......

一个yuanbeth
27分钟前
4
0
总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
今天
4
0
java内存模型

前言 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模...

ls_cherish
今天
4
0
友元函数强制转换

友元函数强制转换 p522

天王盖地虎626
昨天
5
0
js中实现页面跳转(返回前一页、后一页)

本文转载于:专业的前端网站➸js中实现页面跳转(返回前一页、后一页) 一:JS 重载页面,本地刷新,返回上一页 复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a h...

前端老手
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部