Redis - 事务
事务
介绍
Redis 事务是一种将多个命令打包在一起执行的机制,可以确保这些命令在执行期间不会被其他客户端的命令所打断,从而保证了原子性。Redis 事务使用 MULTI、EXEC、DISCARD 和 WATCH 等命令来实现。
以下是 Redis 事务的详细介绍:
-
MULTI 命令:事务的开始。当客户端发送 MULTI 命令时,Redis 会将之后发送的命令都存储在一个队列中,但不会立即执行。如果客户端发送了 MULTI 命令,但又没有发送 EXEC 命令,则队列中的所有命令都会被丢弃。
-
命令入队:在 MULTI 和 EXEC 之间发送的命令都会被放入一个队列中,但不会立即执行。
-
EXEC 命令:执行事务中的所有命令。当客户端发送 EXEC 命令时,Redis 会按照命令入队的顺序执行队列中的所有命令。如果在执行事务期间发生错误,则 Redis 会继续执行后续的命令,直到事务结束。执行事务后,Redis 会将事务中的所有命令的执行结果返回给客户端。
-
DISCARD 命令:取消事务。当客户端发送 DISCARD 命令时,Redis 会丢弃事务队列中的所有命令,并清除事务状态,使其回到非事务状态。
-
WATCH 命令:监视键。当客户端发送 WATCH 命令并指定一个或多个键时,如果在事务执行之前这些键被其他客户端修改,则事务将被取消。WATCH 命令可以用于实现乐观锁。
“WATCH” 命令在 Redis 中用于实现乐观锁的概念。乐观锁是一种并发控制机制,它假设在并发访问的情况下,冲突是比较少见的,因此不会立即对资源进行加锁,而是在更新资源时检查是否存在冲突。如果存在冲突,乐观锁会回退并重试,直到成功。
在 Redis 中,使用 WATCH 命令可以监视一个或多个键,然后在执行事务时检查这些键是否被其他客户端修改。如果在事务执行期间,有任何被监视的键被其他客户端修改,那么该事务会被取消。这种机制类似于乐观锁的检查过程。
通过结合 MULTI 和 EXEC 命令,可以在 WATCH 的基础上构建一个原子性的事务。这样,当多个客户端尝试同时修改某个资源时,可以使用 WATCH 来确保事务的原子性,以避免竞态条件和数据不一致的问题。
悲观锁和悲观锁-
悲观锁:悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到锁。
-
乐观锁:乐观锁(Optimistic Lock),顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。
乐观锁策略:提交版本必须大于记录当前版本才能执行更新。
-
如果在 Redis 事务中,任何一个命令在语法上存在错误,Redis 会立即返回一个错误响应,并且不会执行后续的命令。这意味着即使其他命令是正确的,它们也不会被执行。(全体连坐)
但是,如果所有命令的语法检查都通过了,那么在执行事务期间,如果有某个命令执行失败,它不会影响其他命令的执行。其他命令仍然会被继续执行,并且事务会继续执行到结束。(冤头债主)
Redis事务 VS 数据库事务
1. 单独的隔离操作 | Redis 的事务仅仅是保证事务里的操作会被连续独占的执行,redis 命令执行是单线程架构,在执行完事务内所有指令前是不可能再去同时执行其他客户端的请求的 |
---|---|
2. 没有隔离级别的概念 | 因为事务提交前任何指令都不会被实际执行,也就不存在 ”事务内的查询要看到事务里的更新,在事务外查询不能看到” 这种问题了 |
3. 不保证原子性 | Redis 的事务不保证原子性,也就是不保证所有指令同时成功或同时失败,只有决定是否开始执行全部指令的能力,没有执行到一半进行回滚的能力 |
4. 排它性 | Redis 会保证一个事务内的命令依次执行,而不会被其它命令插入 |