【Redis-04】Redis事务、Lua

Redis事务提供了一种序列化执行命令的方式,确保操作的隔离性。从`MULTI`开始,命令被放入队列,直到`EXEC`触发执行。如果在`EXEC`前有`DISCARD`,则取消事务。事务中的错误处理原则是,错误只会导致报错命令不执行,其余命令仍继续。此外,`WATCH`和`UNWATCH`用于实现乐观锁机制,监控key的变化,若key变动则事务取消。Redis事务不具备回滚功能,不具备原子性,但通过乐观锁和错误处理策略,保证了一定的数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. 前言

为了保证多条命令组合的原子性,Redis提供了简单的事务功能以及集成Lua脚本来解决这个问题。本节首先简单介绍Redis中事务的使用方法以及它的局限性,之后重点介绍Lua语言的基本使用方法,以及如何将Redis和 Lua脚本进行集成,最后给出Redis管理Lua脚本的相关命令。

1. Redis的事务定义

Redis事务是一个单独的隔离操作:

  1. 事务中的所有命令都会序列化、按顺序地执行。
  2. 事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  3. Redis事务的主要作用就是串联多个命令防止别的命令插队。

熟悉关系型数据库的用户应该对事务比较了解,简单地说,事务表示一组动作,要么全部执行,要么全部不执行。例如在社交网站上用户A关注了用户B,那么需要在用户A的关注表中加入用户B,并且在用户B的粉丝表中添加用户A,这两个行为要么全部执行,要么全部不执行,否则会出现数据不一致的情况。

2.Multi、Exec、discard

Redis提供了简单的事务功能,将一组需要一起执行的命令放到multi和exec两个命令之间。multi命令代表事务开始,exec命令代表事务结束,它们之闻的命令是原子顺序执行的,例如下面操作实现了上述用户关注问题。

从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行。

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> sadd user:a:follow user:b
QUEUED
127.0.0.1:6379(TX)> sadd user:b:fans user:a
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 1
2) (integer) 1

在这里插入图片描述
在这里插入图片描述


组队的过程中可以通过discard来放弃组队。

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> sadd zhangsan 23sui
QUEUED
127.0.0.1:6379(TX)> discard
OK

2.1 举🌰

  1. 命令错误
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> sadd k1 v1
QUEUED
127.0.0.1:6379(TX)> sadd k2
(error) ERR wrong number of arguments for 'sadd' command
127.0.0.1:6379(TX)> sadd k3 c
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.

3.事务的错误处理

组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消。
在这里插入图片描述
如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。
在这里插入图片描述

4.悲观锁

悲观锁(Pessimistic Lock) ,顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

5.乐观锁

乐观锁(Optimistic Lock) , 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。 乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。

6. WATCH key [key …]

在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。


有些应用场景需要在事务之前,确保事务中的key没有被其他客户端修改过,才执行事务,否则不执行(类似乐观锁)。Redis提供了watch命令来解决这类问题,表3-2展示了两个客户端执行命令的时序。
在这里插入图片描述

可以看到“客户端-1”在执行multi之前执行了watch命令,“客户端-2”在“客户端-1“执行exec之前修改了key值,造成事务没有执行(exec结果为nil),整个代码如下所示:

127.0.0.1:6379> set key "java"     // 客户端1
OK
127.0.0.1:6379> watch key          // 客户端1
OK
127.0.0.1:6379> multi              // 客户端1
OK

127.0.0.1:6379> append key python   // 客户端2
(integer) 10


127.0.0.1:6379(TX)> append key jedis // 客户端1
QUEUED
127.0.0.1:6379(TX)> exec             // 客户端1
(nil)
127.0.0.1:6379> get key              // 客户端1
"javapython"

Redis提供了简单的事务,之所以说它简单,主要是因为它不支持事务中的回滚特性,同时无法实现命令之间的逻辑关系计算,当然也体现了 Redis的“keep it simple”的特性,下一小节介绍的Lua脚本同样可以实现事务的相关功能,但是功能要强大很多。

======================================================
在第二个终端中watch multi incrby exec 后nil
这是因为乐观锁原因,终端一执行后,版本号会改变。
在这里插入图片描述

7. unwatch

取消 WATCH 命令对所有 key 的监视。

如果在执行 WATCH 命令之后,EXEC 命令或DISCARD 命令先被执行了的话,那么就不需要再执行UNWATCH 了。

8. Redis事务三特性

1.单独的隔离操作
事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
2.没有隔离级别的概念
队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行
3.不保证原子性
事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

9. Lua

9.1 数据类型及其逻辑处理

Lua语言提供了如下几种数据类型:booleans(布尔)numbers(数值)strings(字符串)tables(表格),和许多高级语言相比,相对简单。下面将结合例子对Lua的基本数据类型和逻辑处理进行说明。

  1. 字符串
    在这里插入图片描述

  2. 数组
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  3. 哈希
    在这里插入图片描述

9.2 函数定义

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

boy快快长大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值