使用場景

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

使用限制

  1. 不支援事務回滾

    假設命令 a、b、c, a和b執行ok,執行到 c 的時候發生異常了,那麼 a和b的操作結果是不會回滾的;

  2. 事務內多個命令間不能相互依賴

    收到 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 指令碼的方式來寫

參考: