1.說明:現在假設有一個session要執行若干次的修改處理,就可以考慮將若干操作放到一個事務中,這樣處理可以讓這些操作儀器一起執行或一起取消。Redis中的事務控制沒有傳統SQL中的事務控制那樣智能,redis中事務控制是將所有可以執行的指令都進行執行,不能執行的指令報錯。
2.指令:
• 開啟事務:multi
• 提交事務:exec
• 取消當前隊列的所有操作:discard
舉例說明:
eg1: set age 18 multi set age 99 get age 這時執行結果為18,因為事務開啟了,set age 99沒有提交。 exec eg2: set age 10 set info lee multi incr age incr info(info是字符串不能執行自增操作) exec 執行結果:age的會執行,而incr info的會報錯,這就體現出了不是一起成功一起失敗
eg3:
multi
set name zhangsan
getset age 18
這時會報錯,因為getset不是指令,這一組操作會全部失敗
• 監控一個或多個key:watch 類似樂觀鎖,配合multi使用,一直監控着有沒有人修改,如果中途有其他人修改則會提交失敗。
• 取消對所有key的監控:unwatch,如果watch時提交失敗,我們需要執行unwatch先取消監控,再執行watch再次監控,multi,最后再提交
3.redis事務的三個階段:開啟,入隊,執行
4.redis事務的三個特性:單獨的隔離操作,沒有隔離級別的概念,不保證原子性
3.lettuce事務控制:
• 同步的事務處理機制
package com.yootk.lettuce.transaction; import com.yootk.lettuce.util.RedisConnectionUtil; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.sync.RedisCommands; import java.util.concurrent.TimeUnit; public class SyncTransactionDemo { public static void main(String[] args) throws Exception { StatefulRedisConnection connection = RedisConnectionUtil.getConnection(); // 獲取連接 RedisCommands commands = connection.sync();// 創建同步操作命令 System.out.println("【開啟事務】開啟多行執行:" + commands.multi()); System.out.println("【設置數據】" + commands.set("lee-msg","Hello World")); System.out.println("【設置數據】" + commands.set("black-msg","Black Face")); TimeUnit.SECONDS.sleep(10); // 追加一個延遲處理 System.out.println("【事務提交】" + commands.exec()); // 執行多個語句 RedisConnectionUtil.close(); } }
• 異步的事務處理機制
package com.yootk.lettuce.transaction; import com.yootk.lettuce.util.RedisConnectionUtil; import io.lettuce.core.RedisFuture; import io.lettuce.core.TransactionResult; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.async.RedisAsyncCommands; import io.lettuce.core.api.sync.RedisCommands; import java.util.concurrent.TimeUnit; public class AsyncTransactionDemo { public static void main(String[] args) throws Exception { StatefulRedisConnection connection = RedisConnectionUtil.getConnection(); // 獲取連接 RedisAsyncCommands commands = connection.async(); // 執行語句 RedisFuture multi = commands.multi();// 開啟事務 RedisFuture setCmdA = commands.set("lee-msg", "Hello World"); RedisFuture setCmdB = commands.set("black-msg","Black Face") ; RedisFuture<TransactionResult> exec = commands.exec(); // 自動的執行事務提交 System.out.println("【開啟事務】開啟多行執行:" + multi.get()); System.out.println("【設置數據】" + setCmdA.get()); System.out.println("【設置數據】" + setCmdB.get()); TimeUnit.SECONDS.sleep(5); // 追加一個延遲處理 System.out.println("【事務提交】" + exec.get()); // 返回執行結果 RedisConnectionUtil.close(); } }
• 響應式的事務處理機制
package com.yootk.lettuce.transaction; import com.yootk.lettuce.util.RedisConnectionUtil; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.reactive.RedisReactiveCommands; import java.util.concurrent.TimeUnit; public class ReactiveTransactionDemo { public static void main(String[] args) throws Exception { StatefulRedisConnection connection = RedisConnectionUtil.getConnection(); // 獲取連接 RedisReactiveCommands commands = connection.reactive();// 創建響應式命令 commands.multi().subscribe(temp ->{ System.out.println("【設置數據】" + commands.set("lee-msg", "Hello World").subscribe()); System.out.println("【設置數據】" + commands.set("black-msg","Black Face").subscribe()); try { TimeUnit.SECONDS.sleep(10); // 休眠10秒 } catch (InterruptedException e) { } System.out.println("【事務提交】" + commands.exec().subscribe()); }) ; TimeUnit.SECONDS.sleep(20); // 追加一個等待機制 RedisConnectionUtil.close(); } }
4.SpringDataRedis事務控制:在SpringDataRedis里面,所有的數據庫操作都是通過RedisTemplate展開的,相應的事務處理也可以通過此類直接完成處理。
import java.util.concurrent.TimeUnit; @ContextConfiguration(locations={"classpath:spring/*.xml"}) @RunWith(SpringJUnit4ClassRunner.class) public class TestRedisTemplateTransaction{ @Autowired private RedisTemplate<String,String> stringRedisTemplate; @Test public void testTransaction()throws Exception{ this.stringRedisTemplate.setEnableTransactionSupport(true);//開啟事務支持 this.stringRedisTemplate.multi();//開啟事務操作 this.stringRedisTemplate.opsForValue().set("lee-msg","hello world"); this.stringRedisTemplate.opsForValue().set("black-msg","black face"); TimeUnit.SECONDS.sleep(5); System.out.println("【執行事務】"+this.stringRedisTemplate.exec());//提交 } }