事务
Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!一次性、顺序性、排他性!执行一些列的命令。
Redis事务中没有隔离级别的概念!(可以说是一种伪事务)
所有的命令在事务中,并没有直接执行!只有执行命令的时候才会执行!exec命令
Redis单条命令是保存原子性的,但是事务不保证原子性!
redis的事务:
- 开启事务(multi)
- 命令入队()
- 执行(exec)
取消事务命令discard
有时我们的入队命令是有问题的,此时可以类比java将redis中事务中的异常分为两类
编译型异常:在编译时即不能通过。redis在这种情况下事务中的所有命令都不会执行,即事务中包含语法错误的命令,如下
此时事务中的所有命令都不会被执行运行时异常:命令本身没有错误但可能违反一些逻辑上错误,如对于一个原有的string的值进行自增操作,如下
可以发现此处错误的命令会抛出异常,事务中的其他命令是成功执行了的,在redis中也可以查到另外两个k1和k2的值。
监控
悲观锁:
- 很悲观,认为什么时候都有可能出问题,无论做什么都枷锁,但这样会很消耗性能的
乐观锁: - 很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据的时候去判断下,在此期间是否有人修改过这个数据。
我们先做一个测试:开启两个客户端,在客户端1(我们自己的客户端)中设置money为100,开启事务对其进行操作
同时在客户端2中修改money的值(假设客户端2为别人操作)
此时我们操作自己的客户端并不知道客户端2别人也对money进行了操作,我们预期money结果应该是102,但是结果
这种就和多线程中造成的未加锁状态是一样一样的,所以我们要给money加上锁,乐观锁,使用watch
这次我们会发现执行失败,因为在执行事务时对money施加了乐观锁,在exec执行的时候redis会检查当前money的版本是否有变化,如果有变化则会事务执行失败,解除锁使用UNWATCH即可
我们知道大多数是基于数据版本(version)的记录机制实现的。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个”version”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1。此时,将提交数据的版本号与数据库表对应记录的当前版本号进行比对,如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据。redis中可以使用watch命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key。这样就可以对指定的key加乐观锁了。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了exec,discard,unwatch命令都会清除连接中的所有监视。
有兴趣的还可以看看这篇文章,使用redis分布式锁实现秒杀的
https://www.cnblogs.com/jasonZh/p/9522772.html