文章目录
- Redis中的原子性
- Redis的事物和MySQL事务的区别
- Redis实现事务
- 什么场景下,会使用事务?
- Redis事务相关命令
- watch命令的实现原理
- 总结
Redis中的原子性
Redis的原子性不同于MySQL的原子性。
Redis的事物和MySQL事务的区别
但是注意体会Redis的事务和MySQL事务的区别:
• 弱化的原⼦性:redis没有"回滚机制".只能做到这些操作"批量执⾏".不能做到"⼀个失败就恢复到
初始状态".
• 不保证⼀致性:不涉及"约束".也没有回滚.MySQL的⼀致性体现的是运⾏事务前和运⾏后,结果都
是合理有效的,不会出现中间⾮法状态.
• 不需要隔离性:也没有隔离级别,因为不会并发执⾏事务(redis单线程处理请求).
• 不需要持久性:是保存在内存的.是否开启持久化,是redis-server⾃⼰的事情,和事务⽆关.
Redis实现事务
Redis中为了实现事务,引入了一个队列。
如果一个客户端开启了事务功能,该客户端就会维持一个队列,每次用户输入的命令,都会先进入该队列,然后等待用户输入执行事务的命令后,该队列中的命令才一次被执行,且执行完才会处理其他客户端的命令。
什么场景下,会使用事务?
铁路12306抢票的例子:
总结:redis中事务比MySQL的事务弱化了很多。
Redis事务本质上是在服务器上搞了⼀个"事务队列".每次客⼾端在事务中进⾏⼀个操作,都会把命令先
发给服务器,放到"事务队列"中(但是并不会⽴即执⾏)。⽽是会在真正收到EXEC命令之后,才真正执⾏队列中的所有操作.
因此,Redis的事务的功能相⽐于MySQL来说,是弱化很多的.只能保证事务中的这⼏个操是"连续的",不会被别的客⼾端"加塞",仅此⽽已。
Redis事务相关命令
multi:开启事务
开启事务后,接下来的所有命令都会放入事务队列中,不执行。
exec:执行事务 : 此时才真正执行队列的命令
discard:放弃当前事务,也就是把当前事务队列的命令都丢掉然后退出事务模式。
watch命令:watch监控某个key是否在一个事务执行前发生改了改变。
举个watch命令的例子:
但实际上,最后结果key是222。这对客户端2就不公平了,为什么我set key 333了,结果确是222?
就导致数据不一致的问题。
刚才的场景中,就可以使用watch命令来监控key,看看这个key在事务的multi和exec之间,set key之后,是否在外部被其他客户端修改了。
此时,exec后,在真正执行事务队列的命令时,发现key外部有修改,于是真正执行key 222的时候就出现了(nil),相当于只要发现我watch的key在事务外部有变化,该事务队列就被丢弃了。
watch命令的实现原理
watch的实现,类似一个”乐观锁“
先解释下乐观锁和悲观锁:
乐观锁:加锁之前有一个心里预期,预期接下来的锁冲突的概率较低。
悲观锁:加锁之前有一个心里预期,预期接下来的锁冲突的概率较高。
持有上面两种心态后,对锁冲突的操作,也有不同。
对于持有“乐观“心态的:加锁的代码可能少,成本低。
对于持有“悲观“心态的:加锁的代码可能多,成本高。
redis的watch,是基于“版本号”这种机制,实现的乐观锁。
总结