關系型數據庫事務的作用是保證並發訪問下數據的一致性,Redis事務有些不同,由於Redis是單線程的處理來自client的指令,所以Redis所有命令的執行都是原子性的,舉一個簡單的例子,單個Redis服務器下,並發地執行INCR命令,也不會返回相同的結果。
所以Redis事務的意義在於保證命令的批量順序執行,並且事務執行期間,Redis不會執行來自client的其他請求。有一點需要注意的是,。如果有命令執行失敗,還是會繼續執行剩下的命令,因為Redis沒有異常回滾。
對“Redis事務命令要么全部執行,要么全部不執行”這句事實的理解:如果有命令執行失敗,並不是中斷事務,而是繼續執行剩下的指令,因為Redis不支持異常回滾。全部不執行的情況有 1.沒有執行EXEC命令 2.WATCH的key發生改變 3.DISCARD命令放棄事務。本質上開啟事務后,所有輸入的命令都被緩存在一個隊列中,一旦EXEC,隊列里的指令被一條一條的執行。
關於事務的API
- MULTI 開啟事務
- EXEC 執行任務隊列里所有命令,並結束事務
- DISCARD 放棄事務,清空任務隊列,全部不執行,並UNWATCH
- WATCH key [key1] MULTI執行之前,指定監控某key,如果key發生修改,放棄整個事務執行
- UNWATCH 手動取消監控
Spring Data Redis 事務問題
RedisTemplate來操作Redis,關於事務操作的時候會有問題:
redisTemplate.multi(); redisTemplate.opsForValue().increment("xxx",1); redisTemplate.opsForValue().increment("ttt",1); redisTemplate.exec();
調用會報一個錯誤“No ongoing transaction. Did you forget to call multi? ”查了下,RedisTemplate操作事務不能理所當然地像原生API那么寫,其實RedisTemplate的事務需要自己實現一個SessionCallBack來做事務,所以要這么寫SessionCallback sessionCallback = new SessionCallback() { @Override public Object execute(RedisOperations redisOperations) throws DataAccessException { redisOperations.multi(); // TODO: 2017/11/20 命令1 // TODO: 2017/11/20 命令2 // TODO: 2017/11/20 命令3 return redisOperations.exec(); } }; redisTemplate.execute(sessionCallback);