Redis之eval+lua实现初步
目录
目录 1
1. 前言 1
2. 执行方式 1
3. 执行过程 3
4. 使用原则 3
1. 前言
Redis的实现保证eval的执行是原子的,即使eval执行的lua超时,Redis也不会自动终止执行。
官方说明如下:
|
When a script reaches the timeout it is not automatically terminated by Redis since this violates the contract Redis has with the scripting engine to ensure that scripts are atomic. |
2. 执行方式
截止到5.0.5版本,Redis都是将lua解释为一MULTI+EXEC方式执行。当执行以下Redis语句时:
|
eval "redis.call('set',KEYS[1],ARGV[1]);redis.call('set',KEYS[2],ARGV[2])" 2 k1 k2 12 ab |
观察它的AOF文件,可以发现内幕:
|
*1 // 1表示参数个数,包括命令令本身,也就是说命令不带参数 $5 // 第一个参数的字节数,MULTI命令为五个字节 MULTI // Redis命令字 *3 // 表示共三个参数,包括命令字本身 $3 set // Redis命令字 $2 // 为“k1”的字节数 k1 // Redis Key $2 // 为“12”的字节数 12 // Redis Value *3 $3 set // Redis命令字 $2 k2 $2 ab *1 $4 EXEC |
如果lua脚本有语法错误,可能导致部分执行,如执行下述脚本:
|
eval "redis.call('set',KEYS[1],ARGV[1]);redis.call('incrby',KEYS[2],ARGV[2])" 2 k1 k2 ab 12 |
将得到错误:
|
ERR Error running script (call to f_de45a142dc8b96e1634403ac2a3f4ccfef4d9dc9): @user_script:1: ERR value is not an integer or out of range |
原因是前一段脚本已将k2的值设置为ab,因此为非整数值,不能对该Key做incrby操作。这个时候AOF将只记录已成功执行部分:
|
*1 $5 MULTI *3 $3 set $2 k1 $2 ab *1 $4 EXEC |
所以在使用lua之前,一定要先测试好,排除掉语法错误。不然因Redis不支持回滚,会出现中间状态。如果确实需要回滚,也应当在同一段lua中完成提交或回滚。
Redis缓存每一段执行的lua脚本,并且不会主动释放,除非外部调用Redis命令“SCRIPT FLUSH”。Redis对执行的lua脚本做SHA,并用SHA值唯一标识该段lua脚本,后续可直接调用evalsha来执行该脚本,从而避免每次调用传入大段lua脚本。
另外,也可以执行Redis命令“SCRIPT KILL”来主动终止正在执行的lua脚本。但能终止的lua脚本仅限还未执行过写(write)操作,如果被KILL的lua脚本已执行了任意写操作,则“SCRIPT KILL”不能终止它的执行,这样约束的原因是为保证eval命令的原子性,不出现中间结果。
如果仍然要终止已执行写操作的lua脚本,只能通过执行“SHUTDOWN NOSAVE”方式,以阻止中间结果(half-written)的存在。
对于复杂的lua脚本 ,可执行redis-cli并指定参数“--ldb”,即可简单快捷的调试lua脚本。
3. 执行过程
Lua的执行过程如下:
|
-> 调用lua脚本解释器执行lua脚本 -> lua脚本解释器将lua脚本翻译成redis命令 -> redis状态机中应用lua脚本所执行到的redis命令 -> redis以MULTI+EXEC方式将所执行的redis命令写入到AOF文件 -> 响应客户端执行结果 |
4. 使用原则
使用eval+lua最好遵守以下原则:
1) 执行时间尽可能短,一定要小于连接的超时时长,可使用命令“slowlog get”观察实际情况;
2) 在应用到生产环境之前,测试保证没有语法错误;
3) 不要硬编码Key和Value到脚本中,不然缓存lua脚本的内存越积越多。
Redis之eval+lua实现初步的更多相关文章
- Redis 使用 Eval 多个键值自增操作示例
在PHP上使用Redis 给多个键值进行自增,示例如下: $set['money'] = $this->redis->hIncrByFloat($key, $hour .'_money', ...
- Redis进阶实践之十九 Redis如何使用lua脚本
一.引言 redis学了一段时间了,基本的东西都没问题了.从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何平台上,也可以嵌入 ...
- Redis基于eval的多字段原子增量计算
目录 目录 1 1. 前言 1 2. 优点 1 3. 方法一:使用struct 2 3.1. 设置初始值(覆盖原有的,如果存在) 2 3.2. 查询k1的值 2 3.3. 设置初始值(覆盖原有的,如果 ...
- 在redis中使用lua脚本
在实际工作过程中,可以使用lua脚本来解决一些需要保证原子性的问题,而且lua脚本可以缓存在redis服务器上,势必会增加性能. 不过lua也会有很多限制,在使用的时候要注意. 在Redis中执行Lu ...
- redis中使用lua脚本
lua脚本 Lua是一个高效的轻量级脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能 使用脚本的好处 1.减少网络开销,在Lua脚 ...
- 新姿势!Redis中调用Lua脚本以实现原子性操作
背景:有一服务提供者Leader,有多个消息订阅者Workers.Leader是一个排队程序,维护了一个用户队列,当某个资源空闲下来并被分配至队列中的用户时,Leader会向订阅者推送消息(消息带有唯 ...
- 在redis里面使用lua
Redis从2.6版本开始引入对Lua脚本的支持,通过在服务器中嵌入Lua环境,Redis客户端可以使用Lua脚本,直接在服务端原子的执行多个Redis命令. lua脚本的好处: 减少网络开销.可以将 ...
- Redis中的原子操作(2)-redis中使用Lua脚本保证命令原子性
Redis 如何应对并发访问 使用 Lua 脚本 Redis 中如何使用 Lua 脚本 EVAL EVALSHA SCRIPT 命令 SCRIPT LOAD SCRIPT EXISTS SCRIPT ...
- Springboot与ActiveMQ、Solr、Redis中分布式事物的初步探索
Springboot与ActiveMQ.Solr.Redis中分布式事物的初步探索 解决的场景:事物中的异步问题,当要求数据库与solr服务器的最终一致时. 程序条件: 利用消息队列,当数据库添加成功 ...
随机推荐
- -UI调试工具 SAK 布局 MD
目录 目录 SwissArmyKnife 接入方式 自动初始化版本 支持的功能 可配置项 原理 自定义功能 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndro ...
- phoenix kerberos 连接配置
1. 官网资料 Use JDBC to get a connection to an HBase cluster like this: Connection conn = DriverManager. ...
- IIS 图片 JS CSS 500错误
1.检查站点MIME类型是否可以正常加载
- 【开发笔记】- 在Grails下查看打印真实的SQL
以往我们都是在hibernate里面开启sql,在grails里面只需要在 DataSource.groovy 里面的一个dataSource加入一个 logSql = true即可,但是这样加后发出 ...
- JavaScript数据类型和语法
第一章 类型 1.2 内置类型 使用 typeof 检测对象类型并不是非常安全的行为: // 安全的 typeof undefined // 'undefined' typeof true // 'b ...
- php curl 转为 x-www-form-urlencoded 方式的坑
网上转变的方法基本都是写添加下面这句: curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-fo ...
- Apache加固之目录、文件限制
如果你用类似phpstudy集成平台的话,所有你想要修改的配置基本上在phpstudy上就可以直接设置操作.但如果你的服务器是通过一步步安装的(Apache+PHP+Mysql)的话,那么就要对各功能 ...
- linux下执行python 提示module找不到 要加入系统路劲才找得到
linux/cmd中python路径导入ModuleNotFoundError: No module named 'xxx' import osimport syscurPath = os.pat ...
- 第一册:lesson 133.
原文: Sensational news. question:What reasons did Karen give for a wanting to retire? Have you just m ...
- Odoo模型的内置方法(可按需重写)
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826222.html ==========模型层面========== 一:_table_exist 检查 ...