I. Overview
Many databases involve transaction processing, and of course Redis also has transaction processing. A transaction in Redis is a set of commands and a transaction queue. The commands in the queue are either all executed or none of them are executed. These commands are all executed after we call the EXEC function.
Second, the specific implementation in Spring
In Spring, if we want to implement Redis transactions, we still need to use the RedisTemplate tool class.
The specific implementation is as follows:
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"; // start transaction 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"); // commit the transaction System.out.println(redisTemplate.exec()); System.out.println(listOperations.leftPop(userOneFollowing)); listOperations.remove(userOneFollowing,1,1000);
After executing the command, we can see the following output:
null [4, 11, two, 14, 14] two
When we uncomment int i = 1/0 in the code, we can find the output as follows:
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)
It can be seen that none of the operations in the above transaction are performed.
3. WATCH command
When we operate, it may involve the value of the data you obtained, which is modified by other threads in the process of using it to perform other operations, that is, there is a race problem. At this time, you need to use the WATCH keyword to Solved, after we WATCH a key, if the key is modified before the transaction is executed, the transaction will not be executed.
The specific use is as follows:
//The use of WATCH, note that you can also use UNWATCH to cancel monitoring 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"));Output result:
lysis
We can see that the statements in the transaction are not executed.
4. Summary
Source address:
click to open the link