Redis作为一个内存数据库和MySQL一样有事务,但是Redis事务和MySQL相比,略有一些不同.
原子性:
Redis是有原子性的,但是和Redis有一些不同,原子性是将操作打包到一起来执行,在MySQL中,会保证要么全执行成功,要么全不执行,但是在Redis中,没有这么做,而是要么全执行要么全不执行,没有保证成功.
一致性:
Redis没有约束,也没有回滚机制,所以没有一致性
持久性:
不具备持久性:Redis本身就是内存数据库,数据的存储在内存中,虽然也有持久化机制,但是和事务没啥关系.
不涉及隔离性
Redis是一个单线程模型的服务器程序,所有的请求/事务都是串行执行的.
Redis事务的的主要意义就是"打包",避免其他客户端的命令.插队插到中间,Redis中实现事务时引入了队列(每个客户端都有一个)
开启事务的时候,此时客户端输入命令,就会发给服务器并且进入这个队列中(而不是立即执行),遇到了执行事务命令的操作的时候才会执行,此时就会把队列中的这些任务都按照顺序依次执行.
上述说的每个客户端都有一个意思是:每个客户端都能使用Redis服务器这个队列,而不是客户端都存在一个队列.
我么思考一个问题:为什么Redis的事务不搞得像mysql一样强大?
强大意味着要付出代价,MySQL付出了时间和空间上得代价.
啥时候用到Redis的事务呢?
就是当多个操作需要打包进行的时候,使用事务是比较合适的.
Redis可以嵌入lua脚本,这就意味着,我们可以写一些逻辑,这里就不写了.
还有要记住一点就是当Redis是集群部署的时候,是不支持事务的.
事务相关的命令
MULTI 这个命令是开启事务
EXEC 这个命令是执行事务
DISCARD 放弃当前事务
那在开启是事务的时候,并发送命令给服务器,这时Redis服务器重启了,会是什么效果?
这个效果就是和DISCARD执行的效果一样,放弃当前事务.
还有一个命令就是WATCH,这个命令是用来监控某个key在事务执行前,是否发生变化,就比如说,我开起了事务,设置了一个键值对,还没有执行事务,另一个客户端也设置了一个相同的key,值不一样,那么就可以说这个key在执行事务之前发生了变化,如果发生变化,事务执行的结果就是nil.
下面再说一下WATCH的原理:他其实和线程问题中的"乐观锁"很类似,Redis的WATCH就相当于基于版本号这样的机制,实现了乐观锁.
当执行 watch key这个命令的时候,就给这个可以分配版本号,并记录下来.当执行事务的时候就会进行判定版本号是否一致,一致则进行设置,不一致,返回nil.
其中这个版本号可以理解为"整数".每次修改的时候都会变大,但不是有序变大.