Redis高级应(2)-事务以及LUA脚本

事务

所谓事务(Transaction) ,是指作为单个逻辑工作单元执行的一系列操作

ACID回顾

  • Atomicity(原子性): 构成事务的的所有操作必须是一个逻辑单元,要么全部执行,要么全部不 执行。
  • Consistency(一致性): 数据库在事务执行前后状态都必须是稳定的或者是一致的。
  • Isolation(隔离性): 事务之间不会相互影响。
  • Durability(持久性): 事务执行成功后必须全部写入磁盘。

Redis事务

Redis 事务的本质是一组命令的集合

  • Redis的事务是通过multi、exec、discard和watch这四个命令来完成的。
  • Redis的单个命令都是原子性的,所以这里需要确保事务性的对象是命令集合。
  • Redis将命令集合序列化并确保处于同一事务的命令集合连续且不被打断的执行 、
  • Redis不能保障失败回滚

注意事项
注意!redis的事务远远弱于mysql,严格意义上,它不能叫做事务,只是一个命令打包的批处理,不能
保障失败回滚。
这是官方文档的原话:

It's important to note that even when a command fails, all the other commands in the
 queue are processed – Redis will not stop the processing of commands.

原理分析

  • 调用multi指令后,redis其实是开启了一个命令队列,后续的命令被提交到队列(还没有执行)
  • 期间出现问题了(比如down机),终止操作,队列清空
  • 到exec命令后,批量提交,事务完成

操作演示

192.168.139.187:0>multi
"OK"
192.168.139.187:0>set k1 v1
"QUEUED"
192.168.139.187:0>get k1
"QUEUED"
192.168.139.187:0>exec
1) "OK"
2) "OK"
3) "OK"
4) "v1"
5) "OK"
192.168.139.187:0>

关于回滚

注意!回滚要看两种情况:

  • 直接语法错误,redis完全无法执行,Redis 2.6.5之前的版本不会回滚,之后版本整个事务回滚
  • 执行期的错误,redis不会回滚,其他正确的指令会照样执行

验证:错误的命令,导致回滚(版本:6.2.6)

#旧value是a
192.168.139.187:0>set a a
"OK"
192.168.139.187:0>get a
"a"
#开启事务
192.168.139.187:0>multi
"OK"
#设置成b,语法没有问题,进入队列
192.168.139.187:0>set a b
"QUEUED"
# 语法错误
192.168.139.187:0>set a
"ERR wrong number of arguments for 'set' command"
# 提交事务: 失败,操作失败事务回滚
192.168.139.187:0>exec
"EXECABORT Transaction discarded because of previous errors."
# 最终a的值没有被修改
192.168.139.187:0>get a
"a"

验证:命令语法对,但是数据类型不对,执行期间才会被发现!

#旧值a
192.168.139.187:0>get a
"a"
# 开启事务
192.168.139.187:0>multi
"OK"
#设置新值
192.168.139.187:0>set a b
"QUEUED"
# 语法正确 但是操作的类型正确 a 应该是string 而不是list
192.168.139.187:0>lpush a 1
"QUEUED"
#提交事务 发现lpush a 1  出现错误
192.168.139.187:0>exec
1) "OK"
2) "OK"
3) "OK"
4) "WRONGTYPE Operation against a key holding the wrong kind of value"
5) "OK"
# 最终结果 a 被修改,事务没有被回滚
192.168.139.187:0>get a
"b"

Lua脚本

lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程
序中,从而为应用程序提供灵活的扩展和定制功能。

Lua应用场景:

  • 游戏开发
  • 独立应用脚本
  • Web应用脚本
  • 扩展和数据库插件
  • Nginx + lua开发高性能web应用,限流、防止Sql注入…

Redis使用lua脚本

版本:自2.6.0起可用,通过内置的lua编译/解释器,可以使用EVAL命令对lua脚本进行求值。

时间复杂度:取决于执行的脚本。

使用Lua脚本的好处:

  • 减少网络开销。可以将多个请求通过脚本的形式一次发送,减少网络时延。
  • 原子操作。redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。因此在编写脚本的
    过程中无需担心会出现竞态条件,无需使用事务。
  • 复用。客户端发送的脚本会永久存在redis中,这样,其他客户端可以复用这一脚本而不需要使用
    代码完成相同的逻辑。
    命令格式:
EVAL script numkeys key [key ...] arg [arg ...]

命令说明:

  • script :参数是一段 Lua 5.1 脚本程序。脚本不必(也不应该)定义为一个 Lua 函数
  • numkeys : 用于指定键名参数的个数。
  • key [key …] ,是要操作的键,可以指定多个,在lua脚本中通过 KEYS[1] , KEYS[2] 获取
  • arg [arg …] ,附加参数,在lua脚本中通过 ARGV[1] , ARGV[2] 获取。
    实例:
192.168.139.187:0>eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 one two
1) "key1"
2) "key2"
3) "one"
4) "two"

lua脚本中调用Redis命令

  • redis.call():
    返回值就是redis命令执行的返回值
    如果出错,则返回错误信息,不继续执行
  • redis.pcall():
    返回值就是redis命令执行的返回值
    如果出错,则记录错误信息,继续执行
    注意事项
    在脚本中,使用return语句将返回值返回给客户端,如果没有return,则返回nil
192.168.139.187:0>eval "return redis.call('set',KEYS[1],ARGV[1])" 1 name 清风冷影
"OK"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值