1、简述
Redis 和关系型数据库的事务有着很大的区别,Redis 对事务的支持是非常简单的批处理,即一组命令的集合,事务中的命令会被序列化,执行过程中不会被其他客户端发来的指令干扰。Redis事务总的来说就是一次性、顺序性、排他性的执行一个队列中的一系列指令。
2、特点
1)并不能像传统数据库一样设置事务隔离级别,但是提供了乐观锁机制来避免一些并发问题,在执行事务之前使用关键字 Watch 即可监视某一个键
2)执行过程中产生了错误不会进行回滚,且会继续执行失败指令后续的指令
3)在 Exec 命令发出前,事务内的所有命令均不会被执行
3、关键字
4、错误产生后的行为
1)在 multi 开启后输入命令的过程中如果输入 discard 则代表取消此次组队
2)在 multi 开启后输入命令的过程中如果出现了一些错误,例如关键字拼写错误等,则事务队列组建也会被取消
3)在事务队列组建完成后,Exec执行,其后如果出现一些错误,例如 incr 非数值型的值,则这个错误出现后后续命令并不会被打断
5、关于 Watch(基于乐观锁机制)
Redis 在单客户端访问的时候肯定是天下太平事务执行顺顺利利,但是在多客户连接情况下可能会出现脏读的情况,为了避免这个情况,可以采用 Watch 命令来监视你操作的键,那么在 multi 开启后,exec 执行前,这段时间若你 watch 的 key 有被改动的话,事务就不会执行
6、关于原子性
Redis 的事务的原子性,对于并发的情况,会有失效的情况。即多个连接有其中一个连接因为执行 multi 的过程中有其他连接对 watch 的键进行了修改,那么整个事务就不会执行,在秒杀场景中可能会导致少卖的情况。这种原子性在并发情况下感觉十分局限,那么其实为了保证一组命令的原子性,还有一种方式,那就是 Lua 脚本,把一组指令写入 Lua 脚本,就能保证并发情况下不会产生有的连接执行失效的情况!原理差不多总结起来就是就算你在 Lua 里写出花,执行也是一个命令(eval/evalsha)去执行的,一条命令没执行完,其他客户端是看不到的。但是根据业务的情况不同, Lua 也并非万金油,具体可以参考阅读。