一提到事务,首先想到的是数据库的事务机制ACID, 原子性(Atomicity),一致性(Consistency),隔离性(Isolation)和持久性(Durability)
Redis事务特性
Redis 事务具有两个重要特性:
1) 单独的隔离操作
事务中的所有命令都会被序列化,它们将按照顺序执行,并且在执行过的程中,不会被其他客户端发送来的命令打断。
2) 不保证原子性
在 Redis 的事务中,如果存在命令执行失败的情况,那么其他命令依然会被执行,不支持事务回滚机制。
注意:Redis 不支持事务回滚,原因在于 Redis 是一款基于内存的存储系统,其内部结构比较简单,若支持回滚机制,则让其变得冗余,并且损耗性能,这与 Redis 简单、快速的理念不相符合。
Redis 事务是方便用户一次执行多个命令。执行 Redis 事务可分为三个阶段:
- 开始事务 (multi)
- 命令入队
- 执行事务 (exec)
- 或取消事务 (discard)
不保证原子性例子
命令执行失败:包括语法错误(编译时)和逻辑错误(运行时),语法错误时,都不执行;逻辑错误时,其余执行,仅不执行逻辑错误的命令.
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set aa 1
QUEUED
127.0.0.1:6379> seett bb 1 #语法错误,没有此命令
(error) ERR unknown command `seett`, with args beginning with: `bb`, `1`,
127.0.0.1:6379> set cc 1
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
# 事务所有指令不能执行
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set aa aa
QUEUED
127.0.0.1:6379> incr aa #逻辑错误,字符串不能自加
QUEUED
127.0.0.1:6379> set bb bb
QUEUED
127.0.0.1:6379> get bb
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "bb"
# 事务命令 仅逻辑错误的没执行,其余都执行了
redis监视器
锁机制
悲观锁:很悲观,认为什么时候都会出问题,无论做什么都加锁(效率低).
乐观锁:很乐观,认为什么时候都不会出问题,所以不会上锁(更新数据时判断一下,再次期间是否数据有改动)
mysql,在数据表中加version字段,更新数据先,读取version,当更新数据时,比对version字段有没有被改动过,有改动就放弃更新,没改动则连同version一块更新.
redis有个监视器 WATCH 可以实现乐观锁,
E:\java\Redis-x64-5.0.9>redis-cli
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money out
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379>
# 在上面步骤,开启事务后 但没有执行时运行.
E:\java\Redis-x64-5.0.9>redis-cli
127.0.0.1:6379> decrby money 20
(integer) 80
127.0.0.1:6379>
事务如果执行成功,监视器会自动取消。
如果像上面事务未成功,首先unwatach,取消监视,重新watch,循环上面的业务.