redis

Redis 事务

Redis 中的事务其实是一组命令的集合,命令会被序列化,在事务执行过程中,会按照顺序执行。

一致性、顺序性、排他性的执行一系列的命令

  • Redis 中单条命令是保证原子性的,但是 Redis 中的事务不保证原子性
  • Redis 事务没有隔离级别的概念,没有关系型数据库中事务隔离级别不同导致的问题(脏读、不可重复读、幽灵)

Redis 的事务:

  • 开启事务:MULTI
  • 命令入队:
  • 执行事务:EXECDISCARD 取消事务

使用MULTI开启事务,然后输入一系列命令入队,EXEC执行事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
hominsu-redis-docker:0>MULTI
"OK"
hominsu-redis-docker:0>SET k1 v1
"QUEUED"
hominsu-redis-docker:0>SET k2 v2
"QUEUED"
hominsu-redis-docker:0>GET k2
"QUEUED"
hominsu-redis-docker:0>SET k3 v3
"QUEUED"
hominsu-redis-docker:0>EXEC
1) "OK"
2) "OK"
3) "OK"
4) "OK"
5) "OK"
6) "v2"
7) "OK"
8) "OK"
9) "OK"

DISCARD:取消事务,之前输入的全都不会执行

1
2
3
4
5
6
7
8
hominsu-redis-docker:0>MULTI 
"OK"
hominsu-redis-docker:0>set k1 v1
"QUEUED"
hominsu-redis-docker:0>set k2 v2
"QUEUED"
hominsu-redis-docker:0>DISCARD
"OK"

异常

  • 编译型异常,执行不了
  • 运行时异常,其他命令都能正常运行,错误命令会抛出异常,不会回滚!!!⚠️

编译型异常,执行事务也是报错的,全部命令都不会被执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
hominsu-redis-docker:0>flushdb
"OK"
hominsu-redis-docker:0>MULTI
"OK"
hominsu-redis-docker:0>set k1 v1
"QUEUED"
hominsu-redis-docker:0>set k2 v2
"QUEUED"
hominsu-redis-docker:0>set k3
"ERR wrong number of arguments for 'set' command"
hominsu-redis-docker:0>set k4 v4
"QUEUED"
hominsu-redis-docker:0>EXEC
"EXECABORT Transaction discarded because of previous errors."

运行时错误:中间的 INCR k1 执行会失败,但是其他命令会正常执行,不会回滚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
hominsu-redis-docker:0>MULTI
"OK"
hominsu-redis-docker:0>SET k1 "string"
"QUEUED"
hominsu-redis-docker:0>INCR k1
"QUEUED"
hominsu-redis-docker:0>SET k2 v2
"QUEUED"
hominsu-redis-docker:0>GET k2
"QUEUED"
hominsu-redis-docker:0>EXEC
1) "OK"
2) "OK"
3) "OK"
4) "ERR value is not an integer or out of range"
5) "OK"
6) "OK"
7) "OK"
8) "v2"
9) "OK"

监控

悲观锁

  • 什么操作都要加锁

乐观锁

  • 更新数据的时候判断,在更新期间是否有人修改数据
  • 获取 version
  • 更新的时候比较 version

WATCH key:监控一个 key

正常执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
hominsu-redis-docker:0>set money 100
"OK"
hominsu-redis-docker:0>set out 0
"OK"
hominsu-redis-docker:0>WATCH money
"OK"
hominsu-redis-docker:0>MULTI
"OK"
hominsu-redis-docker:0>DECRBY money 20
"QUEUED"
hominsu-redis-docker:0>INCRBY out 20
"QUEUED"
hominsu-redis-docker:0>EXEC
1) "OK"
2) "80"
3) "OK"
4) "20"
5) "OK"

多个线程对数据进行操作:

  • 监控 money:
1
2
3
4
5
6
7
8
hominsu-redis-docker:0>WATCH money
"OK"
hominsu-redis-docker:0>MULTI
"OK"
hominsu-redis-docker:0>DECRBY money 10
"QUEUED"
hominsu-redis-docker:0>INCRBY out 10
"QUEUED"
  • 上面的事务还没有执行的时候,其他线程修改了 money 的值:
1
2
3
4
hominsu-redis-docker:0>get money
"80"
hominsu-redis-docker:0>set money 1000
"OK"
  • 事务执行失败:
1
hominsu-redis-docker:0>EXEC

事务执行失败后,Redis 会自动释放锁,执行成功也会执行锁

直接继续进行事务即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
hominsu-redis-docker:0>WATCH money
"OK"
hominsu-redis-docker:0>MULTI
"OK"
hominsu-redis-docker:0>DECRBY money 1
"QUEUED"
hominsu-redis-docker:0>INCRBY out 1
"QUEUED"
hominsu-redis-docker:0>EXEC
1) "OK"
2) "999"
3) "OK"
4) "21"
5) "OK"