Redis的事务功能详解
http://ghoulich.xninja.org/2016/10/12/how-to-use-transaction-in-redis/
MULTI、EXEC、DISCARD和WATCH命令是Redis事务功能的基础。
使用MULTI命令便可以进入一个Redis事务。这个命令的返回值总是OK
。此时,用户可以发出多个Redis命令。Redis会将这些命令放入队列,而不是执行这些命令。一旦调用EXEC命令,那么Redis就会执行事务中的所有命令。
相反,调用DISCARD命令将会清除事务队列,然后退出事务。
在事务运行期间,虽然Redis命令可能会执行失败,但是Redis仍然会执行事务中余下的其他命令,而不会执行回滚操作
DISCARD命令可以用来中止事务运行。在这种情况下,不会执行事务中的任何命令,并且会将Redis连接恢复为正常状态。
作为WATCH命令的参数的键会受到Redis的监控,Redis能够检测到它们的变化。在执行EXEC命令之前,如果Redis检测到至少有一个键被修改了,那么整个事务便会中止运行,然后EXEC命令会返回一个Null
值,提醒用户事务运行失败。
Spring Framework 中启动 Redis 事务操作
http://www.cnblogs.com/yangwn/p/5260670.html
@Transactional注解事务不回滚不起作用无效
https://blog.****.net/u011410529/article/details/54287307
Spring声明式事务为何不回滚
https://www.jianshu.com/p/f5fc14bde8a0
声明式事务是通通过AOP动态代理实现的,这样会产生一个代理类来做事务管理,而目标类(service)本身是不能感知代理类的存在的。
对于加了@Transactional注解的方法来说,在调用代理类的方法时,会先通过拦截器TransactionInterceptor开启事务,然后在调用目标类的方法,最后在调用结束后,TransactionInterceptor 会提交或回滚事务,大致流程如下图:
总结,在方法 A 中调用方法 B,实际上是通过“this”的引用,也就是直接调用了目标类的方法,而非通过 Spring 上下文获得的代理类,所以事务是不会开启的。
解决方法:
1、不字节调用,把要调用的声明为bean。
2、用 AopContext.currentProxy()获取到本类的当前代理对象,然后用这个对象去调用该方法。