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());//提交
}
}
