Skip to content

Latest commit

 

History

History
172 lines (143 loc) · 5.23 KB

2018-01-02-Redis事务.md

File metadata and controls

172 lines (143 loc) · 5.23 KB

一、什么是事务

事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。

二、Redis 事务常用命令

这里写图片描述

三、Case 案例

为了说明情况在相对应的命令后面加了解释。

3.1 正确执行

127.0.0.1:6379> MULTI    // 开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED    // QUEUED 表示入队
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> EXEC    // 执行事务
1) OK
2) "v1"
3) OK

3.2 取消事务

127.0.0.1:6379> FLUSHDB    // 清空数据
OK
127.0.0.1:6379> MULTI    // 开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> DISCARD    // 取消事务
OK
127.0.0.1:6379> get k1
(nil)

3.3 语法出错,事务回滚

127.0.0.1:6379> FLUSHDB    // 清空数据
OK
127.0.0.1:6379> MULTI    // 开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3    // 模拟出错
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> EXEC    // 执行事务
(error) EXECABORT Transaction discarded because of previous errors.    // 事务因为前面的错误被取消
127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379> keys *
(empty list or set)

注:如果执行的命令本身语法出错 (在事务中出错),那么这个事务中的所有命令都不会执行。

3.4 非语法错误,事务不回滚

127.0.0.1:6379> FLUSHDB    // 清空数据
OK
127.0.0.1:6379> MULTI    // 开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> INCR k1    // 使 k1 自增 1
QUEUED
127.0.0.1:6379> EXEC    // 执行事务
1) OK
2) OK    // 前两条命令正确执行
3) (error) ERR value is not an integer or out of range    // 由于 v1 是 String 类型不能自增,第三条命令报错
127.0.0.1:6379> mget k1 k2
1) "v1"
2) "v2"

注:如果在事务执行时出错 (在事务中不出错),那么只有出错的命令不执行,其他正确的命令会被执行。

Redis 与传统的关系型数据库事务最大的区别在于,Redis 不支持事务回滚机制。

Redis 的作者在事务功能文档中解释道:不支持复杂的事务回滚机制是因为与 Redis 追求的简单高效主旨不符,并且他认为事务执行出错往往都是编程错误导致的,所以他认为没有必要为 Redis 设计事务回滚功能。

3.5 WATCH 监控 key

正确执行:

127.0.0.1:6379> FLUSHDB    // 清空数据
OK
127.0.0.1:6379> set money 100    // 初始化 money100
OK
127.0.0.1:6379> WATCH money    // 监视 money
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY money 10    //money 减少 10
QUEUED
127.0.0.1:6379> EXEC    // 执行事务,money 变为 90
1) (integer) 90
127.0.0.1:6379> get money
"90"

出错:

127.0.0.1:6379> WATCH money    // 监视 money ,此时 money90
OK
127.0.0.1:6379> DECRBY money 10    // 在事务开始之前将 money 减少 10money80
(integer) 80
127.0.0.1:6379> get money
"80"
127.0.0.1:6379> MULTI    // 开启事务
OK
127.0.0.1:6379> DECRBY money 10    // 在事务中将 money 减少 10
QUEUED
127.0.0.1:6379> EXEC    // 执行事务,没有命令被执行
(nil)
127.0.0.1:6379> get money    // 查看 money 仍然为 80
"80"

注:在对一个 (或几个) key 进行监视之后,如果这个 (或者几个) key 的值在事务开启之前发生变化,那么在事务中操作这个 (几个)key 的命令将会被打断,有点类似乐观锁的作用。

3.6 UNWATCH 取消监视所有 key

127.0.0.1:6379> WATCH money    // 监视 money 当前 money80
OK
127.0.0.1:6379> UNWATCH    // 取消对所有 key 的监视
OK
127.0.0.1:6379> DECRBY money 10    // 在事务执行之前将 money 减少 10 ,当前执行完 money70
(integer) 70
127.0.0.1:6379> get money 
"70"
127.0.0.1:6379> MULTI    // 开启事务
OK
127.0.0.1:6379> DECRBY money 10    //money 减少 10
QUEUED
127.0.0.1:6379> EXEC    // 执行事务,命令被正确执行
1) (integer) 60
127.0.0.1:6379> get money     // money 被改为了 60
"60"

注:在对 key 进行监视之后,如果想要在事务开启之前操作被监视的 key ,那么可以通过 UNWATCH 取消对所有 key 的监控。

四、总结

4.1 事务的三个状态

  • 开始:以 MULTI 开始一个事务
  • 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面
  • 执行:由 EXEC 命令触发事务

4.2 事务特性

  • 原子性:Redis 具备原子性,但是命令执行出错后不支持事务回滚
  • 一致性:Redis 具备一致性
  • 隔离性:Redis 采用单线程执行,因此事务总是以串行的方式执行,因此 Redis 也是具备隔离性的
  • 持久性:Redis 的持久性意味着执行事务产生的结果被永久性的保存到硬盘里,即使服务器宕机,数据也不应该丢失,因此 Redis 的持久性由 Redis 的持久化方案决定。当服务器在 AOF 持久化模型下,当 appendfync 配置为 always 时,Redis 的事务也具备持久性