什么是事务
事务(Transaction)是一组数据库操作或服务端操作的集合,它们被视为一个单独的工作单元。事务具有以下四个重要的特性,通常被称为 ACID 特性:
- 原子性(Atomicity):事务是一个原子操作,要么全部执行成功,要么全部失败回滚,不存在部分执行的情况。如果一个操作在事务中失败,所有已经执行的操作都会被撤销,数据库状态会回到事务开始之前的状态。
- 一致性(Consistency):事务执行后,数据库从一个一致的状态转移到另一个一致的状态。这意味着事务必须满足一组预定义的规则,以确保数据的完整性和一致性,例如,唯一键约束、外键约束等。
- 隔离性(Isolation):多个事务可以并发执行,但每个事务应该被隔离开来,不受其他事务的干扰。隔离性确保在一个事务修改数据时,其他事务不能访问该数据,直到该事务完成。
- 持久性(Durability):一旦事务成功提交,其对数据库的更改应该是永久性的,即使在系统崩溃或断电后,更改也应该保持不变。
事务通常用于处理复杂的数据操作,确保数据的完整性和一致性。
Redis事务
Redis 事务不是严格意义上的事务,只是用于帮助用户在一个步骤中执行多个命令。单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
之所以Redi执行每一个命令都是原子性,因为Redis是单线程执行的。这里我们一直在强调的单线程,只是在处理我们的网络请求的时候只有一个线程来处理,一个正式的Redis Server运行的时候肯定是不止一个线程的,这里需要大家明确的注意一下。例如Redis进行持久化的时候会以子进程或者子线程的方式执行。
Mysql当中针对于并发事务会存在脏读、不可重复读、幻读等情况,那么Redis会有这种情况吗?
对于Redis而言根本不需要考虑这个。因为Redis是单线程的,根本不具备并发事务,并且Redis的事务虽然给人的感觉是将所有Redis命令放到了一个事务,本质上执行事务,就是把这个事务当成了一行命令来处理,然后对事务内的命令也是一行一行执行。
redis事务的主要作用就是串联多个命令防止 别的命令插队
MULTI、EXEC、DISCARD这三个指令构成了 redis 事务处理的基础:
- MULTI:用来组装一个事务,从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,redis会将之前的命令依次执行。
- EXEC:用来执行一个事务
- DISCARD:用来取消一个事务
使用 MULTI、EXEC 和 DISCARD 这三个命令来执行 Redis 事务不能保证多个客户端操作同一个键的并发性。Redis 的事务是在单个客户端内部原子性的,不会阻止其他客户端对同一键的并发操作。
如果需要确保对同一键的并发访问时不会产生竞态条件,你可以使用 WATCH 命令来实现乐观锁。WATCH 允许客户端监视一个或多个键,如果在执行事务期间这些键被其他客户端修改,事务将自动失败。
示例一 事务被成功执行
# 开始事务
MULTI
# 执行多个命令,将它们添加到事务队列中
SET key1 "value1"
SET key2 "value2"
INCR key3
# 执行事务
EXEC
示例二 取消事务,放弃执行事务块内的所有命令。
# 开始事务
MULTI
# 执行多个命令,将它们添加到事务队列中
SET key1 "value1"
SET key2 "value2"
INCR key3
# 取消事务并放弃执行事务块内的所有命令
DISCARD
示例三 事务出错,命令全部回滚
组队中某个命令出现了错误报告,执行时整个队列中所有的命令都会被取消。
# 开始事务
MULTI
# 在事务中执行一系列命令
SET key1 "value1"
INCR key2
INCR key3
# 故意引发错误,使用不存在的命令
set1 key4 "value4"
# 执行事务
EXEC
示例三 事务出错,命令部分回滚
命令组队的过程中没有问题,执行中出现了错误会导致部分成功部分失败。
# 开始事务
MULTI
# 在事务中执行一系列命令
SET key1 "value1"
SET key2 10
# 故意引发错误,尝试使用 INCR 命令递增字符串键 "key1" 的值
INCR key1
# 执行事务
EXEC
WATCH 和 UNWATCH命令
WATCH 和 UNWATCH 是 Redis 中与事务相关的命令,用于实现乐观锁和监视键的功能。它们通常与 MULTI 和 EXEC 命令一起使用来确保事务的原子性和一致性。
WATCH 命令
WATCH 命令用于监视一个或多个指定的键。一旦客户端开始监视键,如果在执行事务期间有其他客户端修改了这些键,事务将自动失败,以防止基于过期的数据进行修改。
WATCH 命令的语法为:WATCH key [key ...],可以监视多个键,以便在这些键被修改时触发事务的失败。
一旦客户端使用 WATCH 监视了某个键,如果在 EXEC 执行事务之前,被监视的键发生了更改,EXEC 将返回一个空回复(nil),表示事务失败。
# 开始监视键 "my_key"
WATCH my_key
# 开始事务
MULTI
# 在事务中执行一些命令,包括监视的键
SET my_key "new_value"
INCR my_counter
# 执行事务
EXEC
# 在这里不需要显式使用 UNWATCH,Redis 会自动取消监视
UNWATCH 命令
UNWATCH 命令用于取消监视所有之前通过 WATCH 命令监视的键。
UNWATCH 命令的语法为:UNWATCH。
这个命令通常用于取消事务之前的监视操作,以便在事务开始之前,客户端可以重新选择监视的键。
# 开始监视键 "my_key"
WATCH my_key
# 取消监视所有键
UNWATCH
# 开始新的监视,监视键 "another_key"
WATCH another_key
# 开始事务
MULTI
# 在事务中执行一些命令,包括新监视的键
SET another_key "new_value"
INCR another_counter
# 执行事务
EXEC
# 在这里不需要显式使用 UNWATCH,Redis 会自动取消监视
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。