redis 简单整理——Lua[十一]
前言
简单介绍一下Lua。
正文
为了保证多条命令组合的原子性,Redis提供了简单的事务功能以及集 成Lua脚本来解决这个问题。
前面提及到pipline,也提及到pipline 并不是原子性的,如果多条命令想达到一定的原子性怎么破呢?
多条语句达到原子性,一般而言,我们想到的会是事务。
简单地说,事务表示一 组动作,要么全部执行,要么全部不执行。
Redis提供了简单的事务功能,将一组需要一起执行的命令放到multi和 exec两个命令之间。multi命令代表事务开始,exec命令代表事务结束,它们之间的命令是原子顺序执行的。
multi命令代表事务开始,exec命令代表事务结束,它们之间的命令是原子顺序执行的。
这里需要解释一下?
前面的pipline是不是原子性的,为什么这么说呢? 因为前面pipline 也是将加入队列,但是不能保证原子性。
如果要停止事务的执行,可以使用discard命令代替exec命令即可。
如果事务中的命令出现错误,Redis的处理机制也不尽相同。
这是我们开发需要关注的地方。
- 命令错误,这是比较幸运的错误。

整个事务是不会去执行的,这种错误还是比较好解决。
- 运行时候错误
就是说运行了第1、2条,然后第3条出错,或者写错了。
可以看到Redis并不支持回滚功能,sadd user:a:follow user:b命令已 经执行成功,开发人员需要自己修复这类问题。
同样即使我们没有发生错误,那么事务也是可能有问题的。
思考一下mysql 有几种情况发生,什么不可重复读等。
这些都是锁的问题,那么就看一下redis里面的锁吧。
有些应用场景需要在事务之前,确保事务中的key没有被其他客户端修 改过,才执行事务,否则不执行(类似乐观锁)。
Redis提供了watch命令来 解决这类问题。
下面执行一下下面的流程,看下变化。

然后你发现该事务没有执行成功。

也就是说一但watch有变化,那么执行就不会进行下去。
Redis提供了简单的事务,之所以说它简单,主要是因为它不支持事务 中的回滚特性,同时无法实现命令之间的逻辑关系计算,当然也体现了 Redis的“keep it simple”的特性.
Lua语言提供了如下几种数据类型:booleans(布尔)、numbers(数 值)、strings(字符串)、tables(表格),和许多高级语言相比,相对简 单。下面将结合例子对Lua的基本数据类型和逻辑处理进行说明
https://www.runoob.com/lua/lua-tutorial.html
上面可以去看看,很快就能学会。
那么看下Lua语言对redis的处理。
- 看下在redis中如何执行Lua语言。
在Redis中执行Lua脚本有两种方法:eval和evalsha。
eval 脚本内容 key个数 key列表 参数列表

除了使用eval,Redis还提供了evalsha命令来执行Lua脚本。
首先要将Lua脚本加载到Redis服务端,得到该脚本的SHA1校验和, evalsha命令使用SHA1作为参数可以直接执行对应Lua脚本,避免每次发送 Lua脚本的开销。这样客户端就不需要每次执行脚本内容,而脚本也会常驻 在服务端,脚本功能得到了复用。

加载脚本:script load命令可以将脚本内容加载到Redis内存中,例如下 面将lua_get.lua加载到Redis中,得到SHA1 为:"7413dc2440db1fea7c0a0bde841fa68eefaf149c"
执行脚本:evalsha的使用方法如下,参数使用SHA1值,执行逻辑和 eval一致。
有点像存储过程。
Lua的Redis API:
Lua可以使用redis.call函数实现对Redis的访问,例如下面代码是Lua使用 redis.call调用了Redis的set和get操作:
redis.call("set", "hello", "world") redis.call("get", "hello")
eval 'return redis.call("get", KEYS[1])' 1 hello "world"
除此之外Lua还可以使用redis.pcall函数实现对Redis的调用,redis.call和 redis.pcall的不同在于,如果redis.call执行失败,那么脚本执行结束会直接返 回错误,而redis.pcall会忽略错误继续执行脚本,所以在实际开发中要根据 具体的应用场景进行函数的选择。
开发提示:
Lua可以使用redis.log函数将Lua脚本的日志输出到Redis的日志文件中, 但是一定要控制日志级别。 Redis3.2提供了Lua Script Debugger功能用来调试复杂的Lua脚本,具体 可以参考:http://redis.io/topics/ldb。
案例
Lua脚本功能为Redis开发和运维人员带来如下三个好处:
·Lua脚本在Redis中是原子执行的,执行过程中间不会插入其他命令。
·Lua脚本可以帮助开发和运维人员创造出自己定制的命令,并可以将这 些命令常驻在Redis内存中,实现复用的效果。
·Lua脚本可以将多条命令一次性打包,有效地减少网络开销。
案例:

实现:

管理Lua 脚本
Redis提供了4个命令实现对Lua脚本的管理,下面分别介绍。
script load script
script exists
此命令用于判断sha1是否已经加载到Redis内存中.
script exists a5260dd66ce02462c5b5231c727b3f7772c0bcc5

这样就说明没有被加载进去。
- script flush
此命令用于清除Redis内存已经加载的所有Lua脚本
- script kill
此命令用于杀掉正在执行的Lua脚本。如果Lua脚本比较耗时,甚至Lua 脚本存在问题,那么此时Lua脚本的执行会阻塞Redis,直到脚本执行完毕或 者外部进行干预将其结束。
模拟一下。
eval 'while 1==1 do end' 0
Redis提供了一个lua-time-limit参数,默认是5秒,它是Lua脚本的“超时 时间”,但这个超时时间仅仅是当Lua脚本时间超过lua-time-limit后,向其他 命令调用发送BUSY的信号,但是并不会停止掉服务端和客户端的脚本执 行,所以当达到lua-time-limit值之后,其他客户端在执行正常的命令时,将 会收到“Busy Redis is busy running a script”错误,并且提示使用script kill或者 shutdown nosave命令来杀掉这个busy的脚本

此时Redis已经阻塞,无法处理正常的调用,这时可以选择继续等待, 但更多时候需要快速将脚本杀掉。使用shutdown save显然不太合适,所以选 择script kill,当script kill执行之后,客户端调用会恢复.

那么kill 是否一定能成功呢? 不一定。
有一点需要注意,如果当前Lua脚本正在执行写操作,那么script kill将不会生效。

上面提示Lua脚本正在向Redis执行写命令,要么等待脚本执行结束要么 使用shutdown save停掉Redis服务。可见Lua脚本虽然好用,但是使用不当破 坏性也是难以想象的。
这种算是灾难模式。
结
下一节bitmaps,这个还是比较关键的,二进制存储,很多业务上需要。
redis 简单整理——Lua[十一]的更多相关文章
- Redis进阶实践之十九 Redis如何使用lua脚本
一.引言 redis学了一段时间了,基本的东西都没问题了.从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何平台上,也可以嵌入 ...
- Redis知识整理
Redis知识整理 转自:https://www.cnblogs.com/rjzheng/p/9096228.html 1.单线程模型 Redis客户端对服务端的每次调用都经历了发送命令,执行命令,返 ...
- 新姿势!Redis中调用Lua脚本以实现原子性操作
背景:有一服务提供者Leader,有多个消息订阅者Workers.Leader是一个排队程序,维护了一个用户队列,当某个资源空闲下来并被分配至队列中的用户时,Leader会向订阅者推送消息(消息带有唯 ...
- Redis中的原子操作(2)-redis中使用Lua脚本保证命令原子性
Redis 如何应对并发访问 使用 Lua 脚本 Redis 中如何使用 Lua 脚本 EVAL EVALSHA SCRIPT 命令 SCRIPT LOAD SCRIPT EXISTS SCRIPT ...
- .NET Web开发技术简单整理
在最初学习一些编程语言.一些编程技术的时候,做的更多的是如何使用该技术,如何更好的使用该技术解决问题,而没有去关注它的相关性.关注它的理论支持,这种学习技术的方式是短平快.其实工作中有时候也是这样,公 ...
- [redis] session 保存到 redis 简单实现
参考资料: [session保存到redis简单实现]http://blog.csdn.net/ppt0501/article/details/46700221 [Redis学习]http://blo ...
- 转载:.NET Web开发技术简单整理
在最初学习一些编程语言.一些编程技术的时候,做的更多的是如何使用该技术,如何更好的使用该技术解决问题,而没有去关注它的相关性.关注它的理论支持,这种学习技术的方式是短平快.其实工作中有时候也是这样,公 ...
- Java中Redis简单入门
Redis是一个开源的,先进的 key-value 存储可用于构建高性能,可扩展的 Web 应用程序的解决方案. Redis官方网网站是:http://www.redis.io/,如下: Redis ...
- MYBATIS 简单整理与回顾
这两天简单整理了一下MyBatis 相关api和jar包这里提供一个下载地址,免得找了 链接:http://pan.baidu.com/s/1jIl1KaE 密码:d2yl A.简单搭建跑项目 2.进 ...
- 哪些CSS是可以被继承的--简单整理
那些CSS是可以被继承的--简单整理1.文本相关属性是继承的:font-size,font-family,line-height,text-index等2.列表相关属性是继承的:list-style- ...
随机推荐
- python中json.dumps() 与json.dump(),json.load()与json.loads()区别?
json.dumps() 将 Python 对象转换为 JSON 字符串,并返回该字符串.而 json.dump() 将 Python 对象转换为 JSON 字符串,并将该字符串写入文件. json. ...
- redis分片sharding实现原理
为什么集群? 通常,为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取.Redis是一个很好的Cache工具.大型网站应用,热点数据量往往巨大,几十G上百G是很正常的事儿,在 ...
- idea vue 格式化 并保存文件 宏 快捷键 ctrl+s
idea 格式化是 reformat Code 存盘是 ctrl+s 所以创建一个宏,先点格式化,再点存盘,然后定义个ctrl+s的快捷键覆盖之前的保存就ok了. 资料: IDEA 配置宏定义 并为宏 ...
- 让 js 失效 Chrome F12 右上角 settings - Preferences - Debugger - Disable JavaScript
说的可能比较长,实际上,F12 右上角 - 右小角 还是挺好找的.
- C#实现软件开机自启动(不需要管理员权限)
目录 原理简介 使用方法 完整代码 原理简介 本文参考C#/WPF/WinForm/程序实现软件开机自动启动的两种常用方法,将里面中的第一种方法做了封装成AutoStart类,使用时直接两三行代码就可 ...
- linux 无法找到“/usr/bin/core_perl/gcc” vscode
解决问题的思路 查看有没有gcc,没有安装 有的话就是,修改安装路径就可以? "/usr/bin/core_perl/gcc".修改成Gcc的绝对路径 我的修改是./usr/bin ...
- 各种O总结及阿里代码规范总结
首先梳理下POJO POJO包括 DO/DTO/BO/VO(所有的POJO类属性必须使用包装数据类型.) 定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值. controller使 ...
- Hibernate之list和iterator
在Hibernate3中将Session.find(),Session.iterator()换成:session.createQuery().list(),session.createQuery(). ...
- MediaCodec 低延时解码
介绍 我们在使用Android的硬解进行解码时,如果是Android11以上则可以使用其特性低延迟,谷歌官方文档 以下是Android 11支持的低时延特性: ANGLE支持:Android 11引入 ...
- 没想到三天10KStar的营销利器MediaCrawler开源作者已经删库了
前言 一站式社交平台数据抓取利器,带你玩转小红书.抖音.快手.B站和微博数据分析 不经意间,来查看MediaCrawler仓库源码,发现作者已经删库了.看来是领奖了.才几天不到的时间Star数量已经直 ...