Redis也有事务,数据库为保证事务正确性,会有ACID的要求原子性,一致性,隔离性,持久性。但是redis的事务记不太一样,首先我们来个对比就知道了。
一 Redis事务和数据的ACID对比
原子性
就是一系列操作,要么失败全失败,要么成功全成功
Redis的命令操作是原子性,单个执行命令成功就成功,失败就失败,但是Redis的事务不是,就是语法错误全失败,但是单独逻辑错误不会。
举个例子 我对 Redis里面v1 v2添加值,对没有的v3做操作,语法没问题但是v3没有,或者对v2座做不符合类型的操作,字符串你让他新增。中间也会报错,但不会全部失败。
一致性
保证整体数据关系没啥变化,比如两个账户互相再怎么操作不能。凭空多钱或者少钱。
针对上面这个Redis非关系型,这个只能靠你自己来保证。
隔离性
并发环境,不同事务操作同一个数据,每个都有自己的完整数据空间
Redis不好意思我是单线程,我压根就没有隔离事务。
持久性
只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
实际上如果 Redis 没有使用 RDB 或 AOF,那么事务的持久化属性肯定得不到保证
具体分析实际还要看Redis事务三步走,开启,入队,执行这几个步骤具体哪个步骤报错来分析,因为有的是可以的有的是不可以的。
[Redis事务的ACID分析](https://www.51cto.com/article/686117.html)
- Redis 具备了一定的原子性,但不支持回滚。
- Redis 不具备 ACID 中一致性的概念。(或者说 Redis 在设计时就无视这点)
- Redis 具备隔离性。
- Redis 无法保证持久性。
二 使用Redis事务
Redis事务本质:一组命令的集合。
Redis事务操作过程
- 开启事务(multi)
- 命令入队
- 执行事务(exec)
所以事务中的命令在加入时都没有被执行,直到提交时才会开始执行(Exec)一次性完成。
事务开启
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> get k1
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> keys *
QUEUED
127.0.0.1:6379> exec # 事务执行
1) OK
2) OK
3) "v1"
4) OK
5) 1) "k3"
2) "k2"
3) "k1"
事务取消
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> DISCARD # 放弃事务
OK
127.0.0.1:6379> EXEC
(error) ERR EXEC without MULTI # 当前未开启事务
127.0.0.1:6379> get k1 # 被放弃事务中命令并未执行
(nil)
三 事务错误
代码语法错误(编译时异常)所有的命令都不执行
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> error k1 # 这是一条语法错误命令
(error) ERR unknown command `error`, with args beginning with: `k1`, # 会报错但是不影响后续命令入队
127.0.0.1:6379> get k2
QUEUED
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> 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 # 这条命令逻辑错误(对字符串进行增量)
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) (error) ERR value is not an integer or out of range # 运行时报错
4) "v2" # 其他命令正常执行
# 虽然中间有一条命令报错了,但是后面的指令依旧正常执行成功了。
# 所以说Redis单条指令保证原子性,但是Redis事务不能保证原子性。