学习总结

原文:https://juejin.im/post/5d29ac845188252cc75e2d5c

redis事务:

redis是否有事务?

redis是有事务的。命令如下:

 

Redis事务从开始到结束通常会通过三个阶段:

1.事务开始

2.命令入队

3.事务执行

数据库事务正确执行的四个基本要素ACID:

即:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

那么,redis事务是否具备这四个要素?

原子性:要么全部执行,要么全部不执行。

redis里面,事务以multi开始,exec执行前面的所有操作:

例子:

1.

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set zhangyuzhen 1
QUEUED
127.0.0.1:6379> set zhangyuzhen1 2
QUEUED
127.0.0.1:6379> getzhangyuzhen
(error) ERR unknown command 'getzhangyuzhen'
127.0.0.1:6379> get zhangyuzhen
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get zhangyuzhen
"1"
127.0.0.1:6379>

结论:redis具有一定的原子性。

2.

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set appledog famle
QUEUED
127.0.0.1:6379> incr appledog
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range
127.0.0.1:6379> get appledog
"famle"


结论:redis事务发生异常不会滚。

为什么不会滚:

因为redis先执行命,后写日志,而mysql数据库是先写日志,再执行操作的,整个过程复杂,不符合redis的定位。

这个其实跟redis的定位和设计有关系,先看看为何我们的mysql可以支持回滚,这个还是跟写log有关系,redis是完成操作之后才会进行aof日志记录,aof日志的定位只是记录操作的指令记录,而mysql有完善的redolog,并且是在事务进行commit之前就会写完成redolog,binlog

 

image

 

要知道mysql为了能进行回滚是花了不少的代价,redis应用的场景更多是对抗高并发具备高性能,所以redis选择更简单,更快速无回滚的方式处理事务也是符合场景。


一致性:
如果事务块出错,因为不会回滚,所以不具有一致性,如果宕机引起的一致性问题可以通过持久化策略来保持,持久化将在后面来说。
 
隔离性:
redis 因为是单线程操作,所以在隔离性上有天生的隔离机制,当redis执行事务时,redis的服务端保证在执行事务期间不会对事务进行中断,所以,redis事务总是以串行的方式运行,事务也具备隔离性。
 
持久性:

取决于redis的持久化模式

  • 纯内存运行,不具备持久化,服务一旦停机,所有数据将丢失
  • RDB模式,取决于RDB策略,只有在满足策略才会执行bgsave,异步执行并不能保证redis具备持久化
  • aof模式,只有将appendfsync设置为always,程序才会在执行命令同步保存到磁盘,这个模式下,redis具备持久化

(将appendfsync设置为always,只是在理论上持久化可行,但一般不会这么操作)

简单总结

  • redis具备了一定的原子性,但不支持回滚
  • redis不具备ACID中一致性的概念(或者说redis在设计就无视这点)
  • redis具备隔离性
  • redis通过一定策略可以保证持久性

redis追求的是简单,高性能,不必受制于传统ACID的束缚。

 





 

posted on 2019-07-15 10:24  小小鱼儿yz  阅读(215)  评论(0编辑  收藏  举报