事務在執行時,會提供專門的屬性保證,包括原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability),也就是 ACID 屬性。
Redis 提供了 MULTI(開啟事務)、EXEC (提交事務)兩個命令來完成事務
原子性
1,命令入隊時就報錯,會放棄事務執行,保證原子性;
2,命令入隊時沒報錯,實際執行時報錯,不保證原子性;
3,EXEC 命令執行時實例故障,如果開啟了 AOF 日志,可以保證原子性。(使用 redis-check-aof 工具檢查 AOF 日志文件,這個工具可以把未完成的事務操作從 AOF 文件中去除。)。如果只有 RDB日志也沒問題,RDB不會在事務執行時執行,所以 RDB 文件中不會記錄只執行了一部分的結果數據。之后用 RDB 恢復實例數據,恢復的還是事務之前的數據。
重點看第二點:
#開啟事務
127.0.0.1:6379> MULTI
OK
#發送事務中的第一個操作,LPOP命令操作的數據類型不匹配,此時并不報錯
127.0.0.1:6379> LPOP key1
QUEUED
#發送事務中的第二個操作
127.0.0.1:6379> DECR key2
QUEUED
#實際執行事務,事務第一個操作執行報錯
127.0.0.1:6379> EXEC
1) (error) WRONGTYPE Operation against a key holding the wrong kind of value
2) (integer) 8
執行失敗Redis并不會回滾;Redis 中并沒有提供回滾機制。雖然 Redis 提供了 DISCARD 命令,但是,這個命令只能用來主動放棄事務執行,把暫存的命令隊列清空,起不到回滾的效果。
補充:
redis 127.0.0.1:6379>type key
此時會顯示出該key存儲在現在redis服務器中的類型,例如:
redis 127.0.0.1:6379>hash
則表示key為以hash類型存儲在redis服務器里的,此時操作這個數據就必須使用hset、hget等操作方法。
如果是zset如下:
redis 127.0.0.1:6379>zset
則表示數據類型為Sorted Sets的。此時就需要使用zadd、zrange等操作方法,否則就會報WRONGTYPE Operation against a key holding the wrong kind of value這個錯誤!
隔離性
1,并發操作在 EXEC 命令前執行,此時,隔離性的保證要使用 WATCH 機制來實現,否則隔離性無法保證;
2,并發操作在 EXEC 命令后執行,此時,隔離性可以保證。
WATCH 機制的作用是,在事務執行前,監控一個或多個鍵的值變化情況,當事務調用 EXEC 命令執行時,WATCH 機制會先檢查監控的鍵是否被其它客戶端修改了。如果修改了,就放棄事務執行,避免事務的隔離性被破壞。然后,客戶端可以再次執行事務,此時,如果沒有并發修改事務數據的操作了,事務就能正常執行,隔離性也得到了保證。
持久性
如果 Redis 沒有使用 RDB 或 AOF,那么事務的持久化屬性肯定得不到保證。
而RBD快照時間比較長,就是AOF的everysec也是有1秒的數據丟失可能性,所以持久性屬性是得不到保證的。
一致性
一致性理解:應用系統從一個正確的狀態到另一個正確的狀態,而ACID就是說事務能夠通過AID來保證這個C的過程。C是目的,AID都是手段。
既然手段達不到保障,一致性也就沒什么談論的必要了。