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

1.在redis里使用EVAL和EVALSHA

可以使用EVAL命令对输入的脚本进行接受结果
  如:   Eval "return 1+1" 0
  ——>(integer)2
而使用evalsha 命令则可以根据脚本的SHA1校验和对接受脚本的结果,但这个命令要求校验和对应的脚本必须至少执行过一次或者这个校验和对应的脚本被scriptload加载过。
 
  如:
  script load "return 1+2" // 会返回一个sha校验
  ->"e13c398af9f2658ef7050acf3b266f87cXXXXXX"
  ->evalsha "e13c398af9f2658ef7050acf3b266f87cXXXXXX" 0
  ->(integer) 3
在脚本比较长的情况下,如果每次调用脚本都需要将整个脚本传给Redis会占用较多的带宽。为了解决这个问题,Redis提供了EVALSHA命令,允许开发者通过脚本内容的SHA1摘要来执行脚本,该命令的用法和EVAL一样,只不过是将脚本内容替换成脚本内容的SHA1摘要。
 
 

2.伪客户端

因为执行Redis命令必须有相应的客户端状态,所以为了执行Lua脚本中包含的Redis命令,Redis服务器专门为Lua环境创建了一个伪客户端,并由这个伪客户端负责处理Lua脚本中包含的所有Redis命令。
Lua脚本使用redis.call函数或者redis.pcall函数执行一个Redis命令,需要完成以下步骤:
  (1).Lua环境将redis.call函数或者redis.pcall函数想要执行的命令传给伪客户端。
  (2).伪客户端将脚本想要执行的命令传给命令执行器。
  (3).命令执行器执行伪客户端传给它的命令,并将命令的执行结果返回给伪客户端。
  (4).伪客户端接收命令执行器返回的命令结果,并将这个命令结果返回给Lua环境。
  (5).Lua环境在接收到命令结果以后,将该结果返回给redis.call函数或者redis.pcall函数。
  (6).接收到结果的redis.call函数或者redis.pcall函数会将命令结果作为函数返回值给脚本中的调用者。

3.lua_scripts字典

除了伪客户端之外,Redis服务器伪Lua环境创建了另一个协作组件是lua_scripts字典,这个字典的键为某个Lua脚本的SHA1校验和(checksum),而字典的值则是SHA1校验和对应的Lua脚本:
如:
  script load "retrun 1+1"
  -> "e13c398af9f2658ef7050acf3b266f87cXXXXXX"
 
这个返回值和载入的脚本是一一对应关系,这个校验值会存在script字典里。服务器会将所有被eval命令执行过的lua脚本,以及被scriptload载入过的脚本保存在字典里。
 
lua_script字典的两个作用
  (1).一个是实现script exists命令
  (2).实现脚本复制功能。
 

4.EVAL命令的实现

EVAL命令的执行过程可以分为以下三个步骤:
  (1)根据客户端给定的Lua脚本,在Lua环境中定义一个Lua函数。
  (2)将客户端给定的脚本保存到lua_scripts字典,等待将来进一步说明。
  (3)执行刚刚才Lua环境中定义的函数,以此来执行客户端给定的Lua脚本。

5.Redis管理Lua脚本

  (1).script load 
  此命令用于将Lua脚本加载到Redis内存中 
  (2).script exists 
  scripts exists sha1 [sha1 …] 
  此命令用于判断sha1是否已经加载到Redis内存中 
  (3).script flush 
  此命令用于清除Redis内存已经加载的所有Lua脚本,在执行script flush后,sha1不复存在。 
  (4).script kill 
  此命令用于杀掉正在执行的Lua脚本。
  6.redis.call和pcall

6.redsi编写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.call('set', 'foo', 'bar')
  local value=redis.call('get', 'foo') --value的值为bar
redis.pcall函数,功能与redis.call相同,唯一的区别是当命令执行出错时,redis.pcall会记录错误并继续执行,而redis.call会直接返回错误,不会继续执行。
 
 
 

在redis里面使用lua的更多相关文章

  1. Redis进阶实践之十九 Redis如何使用lua脚本

    一.引言               redis学了一段时间了,基本的东西都没问题了.从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何平台上,也可以嵌入 ...

  2. 在redis中使用lua脚本

    在实际工作过程中,可以使用lua脚本来解决一些需要保证原子性的问题,而且lua脚本可以缓存在redis服务器上,势必会增加性能. 不过lua也会有很多限制,在使用的时候要注意. 在Redis中执行Lu ...

  3. redis中使用lua脚本

    lua脚本 Lua是一个高效的轻量级脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能 使用脚本的好处 1.减少网络开销,在Lua脚 ...

  4. 新姿势!Redis中调用Lua脚本以实现原子性操作

    背景:有一服务提供者Leader,有多个消息订阅者Workers.Leader是一个排队程序,维护了一个用户队列,当某个资源空闲下来并被分配至队列中的用户时,Leader会向订阅者推送消息(消息带有唯 ...

  5. Redis中的原子操作(2)-redis中使用Lua脚本保证命令原子性

    Redis 如何应对并发访问 使用 Lua 脚本 Redis 中如何使用 Lua 脚本 EVAL EVALSHA SCRIPT 命令 SCRIPT LOAD SCRIPT EXISTS SCRIPT ...

  6. 在redis中使用lua脚本让你的灵活性提高5个逼格

    在redis的官网上洋洋洒洒的大概提供了200多个命令,貌似看起来很多,但是这些都是别人预先给你定义好的,但你却不能按照自己的意图进行定制, 所以是不是感觉自己还是有一种被束缚的感觉,有这个感觉就对了 ...

  7. StackExchange.Redis加载Lua脚本进行模糊查询的批量删除和修改

    前言 使用StackExchange.Redis没有直接相关的方法进行模糊查询的批量删除和修改操作,虽然可以通过Scan相关的方法进行模糊查询,例如:HashScan("hashkey&qu ...

  8. Php+Redis 实现Redis提供的lua脚本功能

    <?php require_once "predis-0.8/autoload.php"; $config['schema'] = 'tcp'; $config['host' ...

  9. python redis客户端使用lua脚本

    有一个需求,为一个key设置一个field存储时间戳,每当有新数据,判断新数据时间戳是否大于之前的时间戳,如果是,更新时间戳,由于依赖中间执行结果,所以使用lua减少客户端和服务端通信次数. #!/u ...

随机推荐

  1. JSP大文件上传断点续传解决方案

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 首先我们需要了解的是上传文件三要素: 1.表单提交方式:post (get方式提交有大小 ...

  2. MCMC & 贝叶斯

    用MCMC做参数估计

  3. RedHat6.2系统安装ipvsadm+keepalived

    一.安装IPVS 软件包下载: 链接:https://pan.baidu.com/s/1zNgPtALbdBTC1H6e0IaZPw 提取码:xm7t 1.检查内核模块,看一下ip_vs 是否被加载 ...

  4. 将JDBC查询出的数据转化为json格式返回

    使用JDBC,json工具使用的org.json /** * ResultSet转JSON * * @param rs * @return * @throws SQLException * @thro ...

  5. JS框架_(JQuery.js)圆形多选菜单选项

    百度云盘 传送门 密码:zb1c 圆形多选菜单选项效果: <!DOCTYPE html> <html lang="en" > <head> &l ...

  6. LocalDate/LocalDateTime与String的互相转换示例(附DateTimeFormatter详解)

    摘自:https://www.jianshu.com/p/b7e72e585a37 LocalDate/LocalDateTime与String的互相转换示例(附DateTimeFormatter详解 ...

  7. eclipse中把选中的代码全部变成大写或者小写的快捷键

    Ctrl+shift+x是把选中的变成大写 Ctrl+shift+y是把选中的变成小写

  8. Boost学习

    使用boost function使用类成员函数作为回调函数 #include <iostream> #include <boost/function.hpp> struct M ...

  9. 关于 oracle10g、oracle client和plsql devement 三者之间的关系

    oracle10g是服务器,如果本机安装了oracle10g,没有必要安装oracle client,只要配置好DNS,就可以使用plsql devement连接     当然你也可以同时安装orac ...

  10. spark MLlib 概念 1:相关系数( PPMCC or PCC or Pearson's r皮尔森相关系数) and Spearman's correlation(史匹曼等级相关系数)

    皮尔森相关系数定义: 协方差与标准差乘积的商. Pearson's correlation coefficient when applied to a population is commonly r ...