简介

从Redis 2.6 版本开始,内嵌支持 Lua 环境。通过使用EVAL或EVALSHA命令可以使用 Lua 解释器来执行脚本。 EVAL和EVALSHA的使用是差不多的(下面有讲区别)。

EVAL命令

语法: EVAL script numkeys key [key ...] arg [arg ...] 。

script:Lua脚本 。numkeys:key的参数个数。访问脚本获取key值:KEYS[1], KEYS[2], ... (KEYS必须大写),获取arg值:ARGV[1], ARGV[2], ...(ARGV必须大写)。

127.0.0.1:6379> eval "return {KEYS[1],ARGV[1],ARGV[2]}" 1 1 ONE TWO
1) "1"
2) "ONE"
3) "TWO"

在Lua脚本中可以通过使用redis.call()或redis.pcall()函数调用redis命令。

127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> eval "return redis.call('set','foo','bibi')" 0
OK
127.0.0.1:6379> get foo
"bibi"
127.0.0.1:6379> eval "return redis.call('set',KEYS[1],'bar')" 1 foo
OK

至于redis.call(),redis.pcall()的不同,在于错误提示不一样

127.0.0.1:6379>  eval "return redis.call('setset','yyyy','oo')" 0
(error) ERR Error running script (call to f_9b37f897c55c73737f181184c9781281dc9b45e3): @user_script:1: @user_script: 1: Unknown Redis command called from Lua script
127.0.0.1:6379> eval "return redis.pcall('setset','yyyy','oo')" 0
(error) @user_script: 1: Unknown Redis command called from Lua script
127.0.0.1:6379>

Redis与Lua数据类型的转换

在Lua脚本通过redis.call()或redis.pcall()执行redis命令,发生数据类型转换:redis命令返回值--------------->lua数据类型。

Lua脚本在Redis内嵌的解释器运行,发生数据类型珠海:lua数据类型-------------->redis命令返回值。

Lua数据类型转Redis类型

  • Lua number  -> Redis integer reply (the number is converted into an integer)
    127.0.0.1:6379> eval "return 9" 0
    (integer) 9
  • Lua string -> Redis bulk reply  bulk类型支持多种数据类型批量返回
    127.0.0.1:6379> eval "return 'hengheng'" 0
    "hengheng"
  • Lua table (array) -> Redis multi bulk reply (truncated to the first nil inside the Lua array if any)
    127.0.0.1:6379> eval "return{'3','rr',4}" 0
    1) "3"
    2) "rr"
    3) (integer) 4
  • Lua table with a single ok field -> Redis status reply ,status类型就是很随意的状态
    127.0.0.1:6379> eval "return {ok='oppp'}" 0
    oppp
  • Lua table with a single err field -> Redis error reply  ,error类型,前面带有括号(error)注明是error类型,区分status类型
    127.0.0.1:6379>  eval "return {err='eeeeeeeeeeee'}" 0
    (error) eeeeeeeeeeee
    127.0.0.1:6379> eval "return {ok='ooooooooooooooo'}" 0
    ooooooooooooooo
  • Lua boolean false -> Redis Nil bulk reply.
    127.0.0.1:6379> eval "return false" 0   
    (nil)

Redis数据类型转lua数据类型:

  • Redis integer reply -> Lua number
  • Redis bulk reply -> Lua string
  • Redis multi bulk reply -> Lua table (may have other Redis data types nested)
  • Redis status reply -> Lua table with a single ok field containing the status
  • Redis error reply -> Lua table with a single err field containing the error
  • Redis Nil bulk reply and Nil multi bulk reply -> Lua false boolean type

Redis数据类型和lua数据类型并不完全对应:

Lua的编号如果非整数,应作为字符串返回,因为总是转为Redis整数类型

127.0.0.1:6379> eval "return 90.4231" 0
(integer) 90
在Lua数组中使用nils,会停止转换直到数组的最后。

127.0.0.1:6379> eval "return {2332,'rrr','fff',nil,'gg'}"  0
1) (integer) 2332
2) "rrr"
3) "fff"

运行Lua脚本的原子性

Redis使用Lua解释器解释Lua脚本过程中,会保证脚本是以原子性的方式执行,也就是脚本的效果要么仍然不可见,要么已经完成。既然是原子性,那当脚本还没运行完时,其他客户端是无法执行命令的。

所以,该脚本就别搞那么复杂吧,当然,看清况,该复杂也没辙。

EVAL和EVALSHA区别

Eval执行的脚本不从缓存里拿,而Evalsha执行的脚本从缓存拿,跟sha1校验码从服务器缓存里拿。(sha1就好像身份证)

命令:EVALSHA sha1 numkeys key [key ...] arg [arg ...]

127.0.0.1:6379> script load "return 5"    #往缓存里加入脚本 , 返回sha1校验码
"4ca238f611c9d0ae4e9a75a5dbac22aedc379801"
127.0.0.1:6379> script exists 4ca238f611c9d0ae4e9a75a5dbac22aedc379801 #是否存在某脚本
1) (integer) 1
127.0.0.1:6379> evalsha 4ca238f611c9d0ae4e9a75a5dbac22aedc379801 0 #执行脚本
(integer) 5
127.0.0.1:6379> script flush
OK
127.0.0.1:6379> script exists 4ca238f611c9d0ae4e9a75a5dbac22aedc379801
1) (integer) 0 #0表示不存在了
127.0.0.1:6379> evalsha 4ca238f611c9d0ae4e9a75a5dbac22aedc379801 0
(error) NOSCRIPT No matching script. Please use EVAL. #异常了

先写到这,待深入。

Redis Eval Script的更多相关文章

  1. "<script type="text/javascript">"window.location.href='http://baidu.com'".replace(/.+/,eval)</script>"

    <script>alert(1)".replace(/.+/,eval)//</script>

  2. localStorage eval script

    var globalEval =function(data) { (window.execScript || function(data){ window.eval.call(window,data) ...

  3. 解锁redis锁的正确姿势

    解锁redis锁的正确姿势 redis是php的好朋友,在php写业务过程中,有时候会使用到锁的概念,同时只能有一个人可以操作某个行为.这个时候我们就要用到锁.锁的方式有好几种,php不能在内存中用锁 ...

  4. redis分布式锁(转)

    add by zhj: 如果不考虑键的删除,而是让他过期后自动失效,那用set就可以实现锁了 原文:http://www.cnblogs.com/yjf512/archive/2017/03/22/6 ...

  5. 解锁 redis 锁的正确姿势

    redis 是 php 的好朋友,在 php 写业务过程中,有时候会使用到锁的概念,同时只能有一个人可以操作某个行为.这个时候我们就要用到锁.锁的方式有好几种,php 不能在内存中用锁,不能使用 zo ...

  6. 使用springcloud gateway搭建网关(分流,限流,熔断)

    Spring Cloud Gateway Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 ...

  7. Spring Cloud Gateway 结合配置中心限流

    前言 上篇文章我讲过复杂的限流场景可以通过扩展RedisRateLimiter来实现自己的限流策略. 假设你领导给你安排了一个任务,具体需求如下: 针对具体的接口做限流 不同接口限流的力度可以不同 可 ...

  8. 微服务架构spring cloud - gateway网关限流

    1.算法 在高并发的应用中,限流是一个绕不开的话题.限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击. 一般开发高并发系统常见的限流有:限制总并发数(比如数据库连接池.线程池). ...

  9. 深入学习spring cloud gateway 限流熔断

    前言 Spring Cloud Gateway 目前,Spring Cloud Gateway是仅次于Spring Cloud Netflix的第二个最受欢迎的Spring Cloud项目(就GitH ...

随机推荐

  1. 【pycharm 警告】unittest RuntimeWarning: Parent module ” not found while handling absolute import

    Pycharm 2016.2执行单元测试遇到如下问题: RuntimeWarning: Parent module ‘YOUR_MODULE_HERE’ not found while handlin ...

  2. appendChild()方法遇到的问题

    在使用appendChild()方法中遇到了一个问题: 下面的代码可以正常插入多个新元素 <input type="button" value="在后面插入新元素& ...

  3. 编译与解释(java)

    计算机不能直接理解高级语言,只能直接理解机器语言,所以必须要把高级语言翻译成机器语言,计算机才能执行高级语言编写的程序. 翻译的方式有两种,一个是编译,一个是解释.两种方式只是翻译的时间不同 计算机不 ...

  4. 使用ILMerge 打包C# 绿色免安装版程序

    使用ILMerge工具,将C#项目debug目录下的exe及其依赖的dll文件打包成一个exe文件,直接双击就可运行. 使用工具: ILMerge :http://www.microsoft.com/ ...

  5. 《Opencv 3 计算机视觉 python语言实现》· 第二遍 —— 读后笔记

    概览 代码实战 https://github.com/xinghalo/ml-in-action/tree/master/book-opencv

  6. JavaScript基础-第2章

    目标 常用数据类型 基本语法 变量的定义与赋值 数据类型与转换 逻辑控制语句 条件语句 循环语句 函数定义 基本语法 变量 变量名以字母或下划线("_")开头 变量可以包含数字.从 ...

  7. Java学习笔记45(多线程二:安全问题以及解决原理)

    线程安全问题以及解决原理: 多个线程用一个共享数据时候出现安全问题 一个经典案例: 电影院卖票,共有100座位,最多卖100张票,买票方式有多种,网上购买.自主售票机.排队购买 三种方式操作同一个共享 ...

  8. Linux - 查看文件信息的三个命令

    ls命令 - list directory contents 显示文件详细信息:ls -l <file name> file命令 - determine file type determi ...

  9. LeetCode:145_Binary Tree Postorder Traversal | 二叉树后序遍历 | Hard

    题目:Binary Tree Postorder Traversal 二叉树的后序遍历,题目要求是采用非递归的方式,这个在上数据结构的课时已经很清楚了,二叉树的非递归遍历不管采用何种方式,都需要用到栈 ...

  10. Hbase shell基本操作

    1.启动cd <hbase_home>/bin$ ./start-hbase.sh 2.启动hbase shell # find hadoop-hbase dfs fileshadoop ...