一、概述
很多数据库都涉及到事务的处理,当然Redis也有事务的处理。Redis中的事务是一组命令集合,及事务队列,队列中的命令要么全部执行,要么都不执行。这些命令是我们在调用EXEC函数后全部执行的。
二、Spring中具体实现
在Spring中我们要实现Redis事务,依然需要使用到RedisTemplate这个工具类。
具体实现如下:
ListOperations<String,Object> listOperations = redisTemplate.opsForList(); redisTemplate.setEnableTransactionSupport(true); String userOneFollowing = "user:1:following"; String userOneFollowers = "user:1:followers"; String userTwoFollowing = "user:2:following"; String userTwoFollowers = "user:2:followers"; //开始事务 redisTemplate.multi(); listOperations.leftPush(userOneFollowing,"two"); listOperations.leftPush(userOneFollowers,"two"); System.out.println(listOperations.leftPop(userOneFollowers)); // int i = 1/0; listOperations.leftPush(userTwoFollowing,"one"); listOperations.leftPush(userTwoFollowers,"one"); //提交事务 System.out.println(redisTemplate.exec()); System.out.println(listOperations.leftPop(userOneFollowing)); listOperations.remove(userOneFollowing,1,1000);
执行命令后,我们可以看见如下输出:
null [4, 11, two, 14, 14] two
当我们取消代码中int i = 1/0处的注释的时候,我们可以发现输出如下:
null java.lang.ArithmeticException: / by zero at RedisTransactionalTest.testTransactional(RedisTransactionalTest.java:43) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
可以看见上面的事务中的操作都没有进行。
三、WATCH命令
在我们进行操作的时候,可能涉及到你获取的数据的值,在你使用其进行其他操作的过程中被其他线程给修改了,也就是存在竟态问题,这个时候就需要使用WATCH关键字来进行解决了,在我们针对某一key进行WATCH过后,如果这个key在事务执行前被修改了,事务就不会执行。
具体使用如下:
//WATCH的使用,注意也可以使用UNWATCH来取消监控 ValueOperations<String,Object> valueOperations = redisTemplate.opsForValue(); valueOperations.set("name","zhangsan"); redisTemplate.watch("name"); valueOperations.set("name","lisi"); redisTemplate.multi(); valueOperations.set("name","wahaha"); redisTemplate.exec(); System.out.println(valueOperations.get("name"));输出结果:
lisi
我们可以看见事务中的语句并没有执行。
四、总结
源码地址:
点击打开链接