Redis 事务

分类:生活杂谈
阅读:76
作者:majingjing
发布:2021-12-13 23:02

[TOC]

Redis 事务

事务相关命令

Multi 命令

Redis Multi 命令用于标记一个事务块的开始。

事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行。

redis 127.0.0.1:6379> MULTI            # 标记事务开始
OK
 
redis 127.0.0.1:6379> INCR user_id     # 多条命令按顺序入队
QUEUED
 
redis 127.0.0.1:6379> INCR user_id
QUEUED
 
redis 127.0.0.1:6379> INCR user_id
QUEUED
 
redis 127.0.0.1:6379> PING
QUEUED
 
redis 127.0.0.1:6379> EXEC             # 执行
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) PONG

Exec 命令

Redis Exec 命令用于执行所有事务块内的命令。

# 事务被成功执行
 
redis 127.0.0.1:6379> MULTI
OK
 
redis 127.0.0.1:6379> INCR user_id
QUEUED
 
redis 127.0.0.1:6379> INCR user_id
QUEUED
 
redis 127.0.0.1:6379> INCR user_id
QUEUED
 
redis 127.0.0.1:6379> PING
QUEUED
 
redis 127.0.0.1:6379> EXEC
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) PONG
 
 
# 监视 key ,且事务成功执行
 
redis 127.0.0.1:6379> WATCH lock lock_times
OK
 
redis 127.0.0.1:6379> MULTI
OK
 
redis 127.0.0.1:6379> SET lock "huangz"
QUEUED
 
redis 127.0.0.1:6379> INCR lock_times
QUEUED
 
redis 127.0.0.1:6379> EXEC
1) OK
2) (integer) 1
 
 
# 监视 key ,且事务被打断
 
redis 127.0.0.1:6379> WATCH lock lock_times
OK
 
redis 127.0.0.1:6379> MULTI
OK
 
redis 127.0.0.1:6379> SET lock "joe"        # 就在这时,另一个客户端修改了 lock_times 的值
QUEUED
 
redis 127.0.0.1:6379> INCR lock_times
QUEUED
 
redis 127.0.0.1:6379> EXEC                  # 因为 lock_times 被修改, joe 的事务执行失败
(nil)

Discard 命令

Redis Discard 命令用于取消事务,放弃执行事务块内的所有命令。

redis 127.0.0.1:6379> MULTI
OK
 
redis 127.0.0.1:6379> PING
QUEUED
 
redis 127.0.0.1:6379> SET greeting "hello"
QUEUED
 
redis 127.0.0.1:6379> DISCARD
OK

Watch 命令

Redis Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断

redis> WATCH lock lock_times
OK

Unwatch 命令

Redis Unwatch 命令用于取消 WATCH 命令对所有 key 的监视。

redis 127.0.0.1:6379> WATCH lock lock_times
OK
 
redis 127.0.0.1:6379> UNWATCH
OK

事务正确理解

代码语法错误, 所有命令不执行

代码语法错误(编译时异常)所有的命令都不执行

> multi
OK
> set k1 v1
QUEUED
> set k2 v2
QUEUED
> error k1 # 这是一条语法错误命令
(error) ERR unknown command `error`, with args beginning with: `k1`, # 会报错但是不影响后续命令入队 
> get k2
QUEUED
> EXEC
(error) EXECABORT Transaction discarded because of previous errors. # 执行报错
> get k1 
(nil) # 其他命令并没有被执行

代码逻辑错误, 其他命令正常执行

代码逻辑错误 (运行时异常) **其他命令可以正常执行 ** >>> 所以不保证事务原子性

> multi
OK
> set k1 v1
QUEUED
> set k2 v2
QUEUED
> incr k1		# 这条命令逻辑错误(对字符串进行增量)
QUEUED
> set k2 v22
QUEUED
> get k2
QUEUED
> exec
1) OK
2) OK
3) ERR value is not an integer or out of range  # 运行时报错
4) OK
5) "v22"  # 其他命令正常执行

# 虽然中间有一条命令报错了,但是后面的指令依旧正常执行成功了。
# 所以说Redis单条指令保证原子性,但是Redis事务不能保证原子性。

Redis的单条命令是保证原子性的,但是redis事务不能保证原子性

  • Redis事务没有隔离级别的概念

  • Redis单条命令是保证原子性的,但是事务不保证原子性!

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

----------------- 队列 set set set 执行 -------------------

事务中每条命令都会被序列化,执行过程中按顺序执行,不允许其他命令进行干扰。

  • 一次性
  • 顺序性
  • 排他性