广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >redis执行lua脚本的实现方法
  • 479
分享到

redis执行lua脚本的实现方法

2024-04-02 19:04:59 479人浏览 独家记忆
摘要

目录1. 语法格式2.类型转换3.lua脚本3.1 script命令3.2 脚本原子性3.3 脚本缓存和EVALSHA3.4 全局变量保护3.5 日志记录从Redis 2.6.0版本

Redis 2.6.0版本开始,redis内置了Lua解释器,并提供了eval命令来解析Lua脚本求值。

1. 语法格式

语法: eval script numkeys keys args

参数: eval — redis提供解析lua脚本的命令

         script — lua脚本

          numkeys — 指定键名参数集(keys)的个数

          keys — 键名参数集,通过全局变量KEYS数组表示,起始下标为1

          args — 键值参数集,通过全局变量ARGV数组表示,起始下标为1

描述:  EVAL命令的语义要求字面量不要直接写在lua脚本中,推荐使用变量来定义lua脚本,并将字面量放在键名参数集keys和键值参数集args中,通过全局变量KEYS和ARGV来获取,这样做的好处是可缓存!在lua脚本中,可以使用两个函数来执行redis命令,分别是:redis.call()和redis.pcall()

例子:


## 第一个eval命令,设置一个key=name,value=sym的字符串
eval "return redis.call('set',KEYS[1],ARGA[1])" 1 name sym
## 第二个eval命令:获取key=name的字符串的值
eval "return redis.call('get',KEYS[1])" 1 name

错误处理:

上面说过,在lua脚本中可以使用call()和pcall()来执行redis脚本,这两个函数的效果是一模一样的,唯一区别就是它们对于错误处理的不同:

①redis.call()在执行命令中发生错误,脚本会停止执行,返回一个脚本错误,错误的输出信息会说明错误造成的原因:

②redis.pcall()执行命令出错时将捕获错误并返回表示错误的Lua表类型

2.类型转换

当 Lua 通过 call() 或 pcall() 函数执行 Redis 命令的时候,命令的返回值会被转换成 Lua 数据结构;同样地,当Lua脚本在 redis内置解释器里运行时,Lua的返回值也会被转换成Redis类型,然后由EVAL将值返回客户端。lua类型与redis类型之间存在一一转换的关系:

redis -> lua

redis类型

lua类型

描述

redis_integer

lua_number

redis整数转为lua数字

redis_bulk

lua_string

redis bulk回复转为lua字符串

redis_multi bulk

Lua_table

redis 多条bulk回复转为Lua 表

redis_status

lua_table

redis状态回复转为lua表,表内ok域包含状态信息

redis_error

lua_table

redis错误回复转为lua表,表内的err域包含错误信息

redis_nil、

redis_multi nil

lua_boolean_false

redis的nil回复和nil多条回复转为lua的布尔值false

lua -> redis

lua类型

redis类型

描述

lua_number

redis_integer

lua数字转为redis整数

lua_string

redis_bluk

lua字符串转为redis bulk回复

lua_table、

lua_array

redis_multi bulk

lua表(数组)转为redis多条bulk回复

lua_table_ok

redis status

一个带单个ok域的lua表,转为redis

状态回复

lua_table_err

redis_error

一个带单个err域的lua表,转为redis

错误回复

lua_boolean_false

redis nil

lua布尔值false转为redis的nil回复

从lua转换到redis有一条额外的规则,这条规则没有与其相对应的redis转换为lua的规则:

lua_boolean_true -> redis_integer_1,lua布尔值true转为redis整数1

3.lua脚本

3.1 script命令

redis提供了以下几个script命令,用于对于脚本子系统进行控制:

script flush:清除所有的脚本缓存

script load:将脚本装入脚本缓存,不立即运行并返回其校验和

script exists:根据指定脚本校验和,检查脚本是否存在于缓存

script kill:杀死当前正在运行的脚本(防止脚本运行缓存,占用内存)

3.2 脚本原子性

redis使用单个lua解释器去运行所有脚本,并且保证脚本会以原子性的方式去执行,意味着当某个脚本在运行时,不会有其它脚本或者redis命令被执行!所以,如果当前脚本运行很慢,服务器可能会因为正忙而无法执行命令,如:

每个脚本都有一个最大执行时间限制,默认值是5s。最大执行时间的长短由配置文件redis.conf的lua-time-limit选项来控制,或直接使用config get和config set命令来修改。当一个脚本执行达到最大执行时间,redis不会主动结束它,它会进行下面几个步骤:

①redis记录一个脚本正在超时运行

②redis开始重新接受其它客户端请求,但只接受执行script kill命令和shutdown nosave两个命令,若客户端执行其它命令,redis会返回busy错误。

③如果脚本只执行过读操作,使用script kill命令可以立即停止此脚本;如果脚本执行过写操作,只允许shutdown save/nosave命令,通过停止服务器来阻止当前数据写入磁盘。(此时服务器关闭,数据不会被保存)

 

3.3 脚本缓存和EVALSHA

redis有一个内部的脚本缓存机制,它不会每次都重新编译脚本,反倒是它会将所有运行过的脚本永久保存在脚本缓存中(因为redis发现脚本体积非常小,即使量很大,甚至经常修改,储存这些脚本的内存也是微不足道的)。清空脚本缓存只有唯一一个方式,就是执行script flush命令。使用eval命令执行脚本时,每次都要发送脚本主体,如果脚本足够复杂,这会付出无谓的网络带宽。redis基于对lua的缓存,它实现了evalsha命令。

evalsha命令和eval命令效果一样,都是解释lua脚本执行,但是evalsha命令的第一个参数不是脚本主体,而是脚本的SHai校验和,这个校验和可以通过script load命令得到。evalsha命令执行过程分两步:

①如果redis服务器保存了给定SHA1校验和所指定的脚本,就会执行该脚本

②如果redis服务器没保存给定SHA1校验和所指定的脚本,它就会返回一个特殊错误,告知客户端使用eval命令去执行

如下图所示:

 

3.4 全局变量保护

redis的lua脚本不允许创建全局变量,如果脚本需要在多次执行之间维持某种状态,可以借助外部redis key来保存状态,每次脚本执行前,获取redis相对应的key赋值给局部变量。在lua脚本中创建或访问一个全局变量,都会引起脚本停止,eval命令会返回一个错误:

redis的全局变量保护并不是百分百成功,有时候会在脚本中混入lua全局状态,可能会引发AOF持久化和主从复制都无法得到保证。redis建议不要在脚本中使用全局变量,可以使用local关键字定义脚本中的变量!

3.5 日志记录

在redis中使用脚本不会自动记录日志,需要我们在脚本使用redis.log()手动保存日志信息。脚本保存的日志,只有那些与redis实例所设置的日志等级相同或更高级才会被记录。语法:redis.log(loglevel,message)。其中,message表示要记录的日志信息,是一个字符串;loglevel表示redis日志等级,有4个取值:

   redis.LOG_DEBUG

   redis.LOG_VERBOSE

   redis.LOG_NOTICE

   redis.LOG_WARNING

到此这篇关于redis执行lua脚本的实现方法的文章就介绍到这了,更多相关redis执行lua内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: redis执行lua脚本的实现方法

本文链接: https://www.lsjlt.com/news/158251.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • redis执行lua脚本的实现方法
    目录1. 语法格式2.类型转换3.lua脚本3.1 script命令3.2 脚本原子性3.3 脚本缓存和EVALSHA3.4 全局变量保护3.5 日志记录从redis 2.6.0版本...
    99+
    2022-11-12
  • redis怎么执行lua脚本
    小编给大家分享一下redis怎么执行lua脚本,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!从redis 2.6.0版本开始,redis内置了Lua解释器,并提供...
    99+
    2023-06-21
  • Redis中如何执行Lua脚本
    今天就跟大家聊聊有关Redis中如何执行Lua脚本,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。前言Redis从2.6版本开始引入对Lua脚本的支持...
    99+
    2022-10-18
  • springboot中使用redis并且执行调试lua脚本
    目录原因:1、创建一个基本的web项目2、配置redis3、测试redis 的lua脚本4、技术点5、调试方式1、进入服务关闭关闭正在运行的服务器2、从命令行启动redis3、在lu...
    99+
    2022-11-13
  • 基于Redis实现分布式锁的方法(lua脚本版)
    1、前言 在Java中,我们通过锁来避免由于竞争而造成的数据不一致问题。通常我们使用synchronized 、Lock来实现。但是Java中的锁只能保证在同一个JVM进程内中可用...
    99+
    2022-11-12
  • PHP和Redis中的LUA脚本使用方法
    PHP和Redis中的LUA脚本使用方法LUA 是一种轻量级的脚本语言,旨在提供高效的嵌入式扩展功能。Redis 是一种开源的 NoSQL 数据库,提供高效的键值存储和缓存功能。在 Redis 中使用 LUA 脚本可以大大提高数据处理效率和...
    99+
    2023-05-15
    PHP redis Lua脚本
  • 通过redis的脚本lua实现抢红包功能的方法
    这篇文章主要讲解了通过redis的脚本lua实现抢红包功能的方法,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。redis 脚本介绍Redis从2.6版本开始,通过内嵌支持Lua...
    99+
    2022-10-18
  • Redis Lua脚本实现ip限流示例
    目录引言相比Redis事务来说,Lua脚本有以下优点Lua脚本Java代码IP限流Lua脚本引言 分布式限流最关键的是要将限流服务做成原子化,而解决方案可以使使用redis+lua或者nginx+lua技术进行实现,通过...
    99+
    2022-07-15
    Redis Lua ip限流 Redis Lua
  • Redis Lua脚本实现ip限流示例
    目录引言相比Redis事务来说,Lua脚本有以下优点Lua脚本java代码IP限流Lua脚本引言 分布式限流最关键的是要将限流服务做成原子化,而解决方案可以使使用redis+lua或...
    99+
    2022-11-13
  • 怎么用Redis Lua脚本实现ip限流
    这篇文章主要讲解了“怎么用Redis Lua脚本实现ip限流”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用Redis Lua脚本实现ip限流”吧!引言分布式限流最关...
    99+
    2023-07-02
  • Redis进阶应用:Redis+Lua脚本实现复合操作
    一、引言Redis是高性能的key-value数据库,在很大程度克服了memcached这类key/value存储的不足,在部分场景下,是对关系数据库的良好补充。得益于超高性能和丰富的数据结构,Redis已...
    99+
    2022-10-18
  • Redis中lua脚本实现及其应用场景
    目录1. Redis Lua脚本概述2. Redis Lua脚本的优势3. Redis Lua脚本的应用场景4. Redis Lua脚本的使用方法5. Java中使用redis的lua脚本5.1. 添加Redis依赖 在...
    99+
    2023-04-20
    Redis lua脚本 Redis lua
  • Redis | 第9章 Lua 脚本与排序《Redis设计与实现》
    目录前言1. Lua 脚本1.1 Redis 创建并修改 Lua 环境的步骤1.2 Lua 环境协作组件1.3 EVAL 命令的实现1.4 EVALSHA 命令的实现1.5 脚本管理命令的实现1.6 脚本复制1.6.1 EVAL、SCRI...
    99+
    2017-01-01
    Redis | 第9章 Lua 脚本与排序《Redis设计与实现》
  • ansible执行shell脚本的方法
    1. 编写脚本:pb_shell.sh wfq@ubuntu:~/playbook$ cat pb_shell.sh #!bin/sh echo "today(`date`) is a nice day, sinc...
    99+
    2022-06-04
    ansible执行shell脚本
  • jenkins执行python脚本的方法
    在jenkins上打算运行一段python脚本,查到一些常用的方法,下面会介绍。还遇到了版本兼容性问题导致的怎么都执行不成功,最终试了各种版本,定位到兼容性问题,真是各种坑。一般有三种方法:1.安装执行python的插件: Python ...
    99+
    2023-01-31
    脚本 方法 jenkins
  • redis lua脚本实战和减库存的实现是怎样的
    这篇文章给大家介绍redis lua脚本实战和减库存的实现是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。前言我们都知道redis是高性能高并发系统必不可少的kv中间件,它以高性能,高并发著称,我们常常...
    99+
    2023-06-21
  • hive-shell批量命令执行脚本的实现方法
    如下所示: #!/usr/bin/bash HADOOP_HOME="/opt/module/cdh-5.3.6-ha/hadoop-2.5.0-cdh5.3.6" HIVE_HOME='/opt/module/cd...
    99+
    2022-06-04
    hive shell 命令
  • jenkins实现shell脚本化定时执行任务的方法
    1.开发需求socket连接的auction拍卖jar包服务更新重启前半小时切走nginx的访问请求。 socket发起请求之后不需要nginx执行交互可以断开了,但是socket这...
    99+
    2022-11-12
  • jenkins 实现shell脚本化定时执行任务的方法
    1.开发需求socket连接的auction拍卖jar包服务更新重启前半小时切走nginx的访问请求。 socket发起请求之后不需要nginx执行交互可以断开了,但是socket这个任务在auction拍卖任务没结束前...
    99+
    2022-06-04
    jenkins实现shell脚本定时执行任务 jenkins定时执行任务
  • python脚本执行的方法是什么
    Python脚本可以通过以下几种方法来执行:1. 在命令行中执行:可以直接在命令行中输入"python 脚本文件.py"来执行脚本文...
    99+
    2023-10-19
    python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作