使用場景
redis一個命令執行是單執行緒的,不用擔心併發衝突,如果你想有幾個命令想像一個命令一樣,在這幾個命令執行過程中不會執行別的客戶端發來的命令 ,也就是原子性,就可以用 redis Transaction
使用方式
redis 命令
multi // 標識事務起始
command-1
command-2
command-3
exec // 開始執行
redis-server 再接收到 exec 命令的時候,才真正開始順序執行事務裡的命令,然後返回全部命令執行結果
可以用 discard 命令取消事務
使用 Jedis 執行 Transaction (官方例子)
jedis的api和原始 redis 命令非常貼近,沒有什麼學習成本 知道redis command就會用
Transaction t = jedis.multi();
t.set("fool", "bar");
Response<String> result1 = t.get("fool"); // 這邊的response 現在還是空的, 再exec後才能獲取到實際的值
t.zadd("foo", 1, "barowitch");
t.zadd("foo", 0, "barinsky");
t.zadd("foo", 0, "barikoviev");
Response<Set<String>> sose = t.zrange("foo", 0, -1); // get the entire sortedset
t.exec(); // dont forget it
String foolbar = result1.get(); // use Response.get() to retrieve things from a Response
使用限制
不支援事務回滾
假設命令 a、b、c, a和b執行ok,執行到 c 的時候發生異常了,那麼 a和b的操作結果是不會回滾的;事務內多個命令間不能相互依賴
收到 exec 後 redis-server 才開始執行,執行完畢後返回所有結果; 所以事務內多個命令之間不能有依賴,如 command-1 的返回值,不能作為下一個 command-2 的輸入,因為此時獲取不到結果
錯誤示範
Transaction t = jedis.multi();
if(t.get("key1").equals("something")) // exec之前這邊是拿不到結果的
t.set("key2", "value2");
else
t.set("key", "value");
t.exec();
如果多個命令間有依賴 或者要做異常處理,並且需要原子執行,可以考慮用 script lua 指令碼的方式來寫
參考: