原子性:把多个操作,打包成一个整体了
一致性:事务执行之前,和之后,数据都不能离谱
持久性:事务中做出的修改都会存硬盘
隔离性:事务并发执行,涉及到的一些问题~
原子性:Redis的事务到底有没有原子性?存在争议!
最原本的含义,是把多个操作打包到一起,要么全部都执行(不保证成功),要么全都不执行~
Redis做到了上述的含义~
但是MySQL这里的原子性,走的更远,也是把多个操作打包到了一起,要么全部执行成功,要么全都不执行。
redis如果事务中若干个操作,存在有失败的,就失败吧。
MySQL如果事务中有操作执行是啊比,要进行回滚!把中间已经执行的操作,全都回退了~
redis没有约束,也没有回滚机制,事务执行过程中如果某个修改操作出现失败,就可能引起不一致的情况。
redis本身就是内存数据库,数据是存储再内存中的。虽然redis也有持久化机制~
但是这里的持久化机制,和事务没有啥直接关系~
Redis是一个单线程模型的服务器程序,所有的请求/事务,都是“串行”执行的~
Redis的事务,主要的意义,就是为了“打包”,避免其他客户端的命令,插队插到中间~
Redis中实现事务,是引入了队列
开启事务的时候,此时客户端输入的命令,就会发给服务器并且进入这个队列中(并不是立即执行)
当遇到了“执行事务”命令的时候,此时就会把队列中的这些任务都按照顺序依次执行~
主线程会把事务中的操作都执行完,再执行别的客户端。
MySQL的事务,在背后付出了很大的代价~
空间上,要花费更多的空间来存储更多的数据.
时间上,也要有更大的执行开销。
正是因为MySQL上述的问题,才有了Redis上场的机会~
在服务器的事务队列中,保存了上述请求。
此时如果另外开一个客户端,再尝试查询这几个key对应的数据,是查不到的。
当开启事务,并且给服务器发送若干个命令之后,此时服务器重启~此时的这个事务咋办?
此时的效果其实就等同于discard。
watch的实现,类似一个“乐观锁”
乐观锁和悲观锁:不是指某个具体的锁,而是指的是某一类锁的特性
乐观锁:加锁之前,就有一个心理预期,预期接下来的锁冲突的概率比较低
悲观锁:加锁之前,就有一个心理预期,预期接下来的锁冲突的概率比较高
锁冲突概率高和冲突概率低,接下来要做的工作是不一样的~~
watch就相当于是基于版本号这样的机制,来实现了“乐观锁”
当执行watch key 的时候,就会给这个key安排一个版本号
版本号可以理解成一个“整数”
每次在修改的时候,版本号都会“变大”
如果一致,说明当前key在事务开启到最终执行这个过程中,没有别的客户端修改
于是才能真正进行设置
如果不一致,说明key在其他客户端中改过了,因此此处就丢弃事务中的操作~
exec返回nil