事務中的全部操作在資料庫中是不可分割的,要麼全部完成,要麼全部不執行。
交易的執行使資料從一個狀態轉換為另一個狀態,在交易開始之前和交易結束之後,資料庫的完整性約束沒有被破壞。
交易的隔離性要求每個讀寫交易的物件對其他交易的操作物件相互分離,即該交易提交前對其他交易都不可見。
資料庫執行交易後,資料的修改要被持久化保存下來。當資料庫重啟後,資料的值需要是被修改後的值。
Redis交易的執行包含了三個步驟,具體如下:
127.0.0.1:6379> multi OK 127.0.0.1:6379> set t1 v1 QUEUED 127.0.0.1:6379> set t2 v2 QUEUED 127.0.0.1:6379> setget t3 (error) ERR unknown command 'setget' 127.0.0.1:6379> set t4 v4 QUEUED 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get t4 (nil)說明:在執行exec指令之前,如果發生語法錯誤(使用了不存在的指令),那麼指令入隊時, Redis就會報錯並且記錄錯誤,等到執行Exec命令之後,Redi會拒絕所有提交的命令,事務執行失敗。這種情況Reids的事務是可以支援原子性。 情況二範例說明
127.0.0.1:6379> multi OK 127.0.0.1:6379> incr s2 QUEUED 127.0.0.1:6379> set a1 v1 QUEUED 127.0.0.1:6379> set a2 v2 QUEUED 127.0.0.1:6379> exec 1) (error) ERR value is not an integer or out of range 2) OK 3) OK 127.0.0.1:6379> get a2 "v2"說明: s2的值為v2,當執行incr指令時報報錯,因為incr只能新增integer的型別值,但是這種情況下我們發現Redis的事務沒有進行回滾,後面的指令能夠執行成功,所以這種情況下式無法保證事務的原子性。 Redis交易的支援一致性嗎? 情況一:命令入隊時就報錯針對第一種情況,事務本身就會被放棄執行,所以可以保證事務的一致性。 情況二:命令入隊時沒報錯,實際執行時報錯針對第二種情況,有錯誤的命令不會被執行,正確的命令可以正常執行,也不會改變資料庫的一致性。 情況三:Exec執行指令Redis實例發生故障
127.0.0.1:6379> get blance "100" 127.0.0.1:6379> watch blance OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> decrby blance 10 QUEUED 127.0.0.1:6379> incrby blance 10 QUEUED 127.0.0.1:6379> exec (nil)客戶端2:
127.0.0.1:6379> get blance "100" 127.0.0.1:6379> set blance 90 OK 127.0.0.1:6379> get blance "90"說明:客戶端1使用watch偵測balance,開啟交易後,在客戶端2執行更改balance的值操作,模擬其他客戶端在事務執行期間更改watch監控的數據,然後再執行客戶端1的EXEC命令,發現事務未成功執行。
Redis的事務無法支援持久性,如果Redis使用了RDB模式,一個事務執行後,當下一次的RDB快照還未執行前,Redis發生了實例宕機,那麼這種情況下,事務修改的資料是無法保證持久化的,如果Redis採用AOF模式,如論持久化配置為no、everysec和always都可能會存在資料遺失,所以,不管Redis採用那種持久化模式,事務的持久性都無法支援。
以上是Redis事務如何實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!