redis與memcached對比,redis不僅適合做緩存,而且可以做存儲,這就有點數據庫的影子了。說到數據庫,事務是一個很重要的一個方面。
數據庫事務
(簡稱:事務)是數據庫管理系統執行過程中的一個邏輯單位,由一個有限的數據庫操作序列構成。
一個數據庫事務通常包含了一個序列的對數據庫的讀/寫操作。它的存在包含有以下兩個目的:
1.為數據庫操作序列提供了一個從失敗中恢復到正常狀態的方法,同時提供了數據庫即使在異常狀態下仍能保持一致性的方法。
2.當多個應用程序在并發訪問數據庫時,可以在這些應用程序之間提供一個隔離方法,以防止彼此的操作互相干擾。
事務約束
當事務被提交給了DBMS(數據庫管理系統),則DBMS(數據庫管理系統)需要確保該事務中的所有操作都成功完成且其結果被永久保存在數據庫中,如果事務中有的操作沒有成功完成,則事務中的所有操作都需要被回滾,回到事務執行前的狀態;同時,該事務對數據庫或者其他事務的執行無影響,所有的事務都好像在獨立的運行。
通過事務的約束條件,可以總結出四個特點
原子性(Atomicity):事務作為一個整體被執行,包含在其中的對數據庫的操作要么全部被執行,要么都不執行。
一致性(Consistency):事務應確保數據庫的狀態從一個一致狀態轉變為另一個一致狀態。一致狀態的含義是數據庫中的數據應滿足完整性約束
隔離性(Isolation):多個事務并發執行時,一個事務的執行不應影響其他事務的執行
持久性(Durability):已被提交的事務對數據庫的修改應該永久保存在數據庫中
有興趣的更深了解事務相關,可以關注下事務傳播屬性,事務隔離級別。
本文主要演練下redis對事務的支持效果。
1 相關命令
命令 | 作用 | 可用版本 | 時間復雜度 | 返回值 |
WATCH key [key ...] | 監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那么事務將被打斷。 | >= 2.2.0 | redis啟動服務,O(1) | 總是返回? |
MULTI | 標記一個事務塊的開始 | >= 1.2.0 | O(1) | 總是返回?OK |
EXEC | 執行所有事務塊內的命令。 redis有什么用?假如某個(或某些) key 正處于?WATCH?命令的監視之下,且事務塊中有和這個(或這些) key 相關的命令,那么?EXEC?命令只在這個(或這些) key 沒有被其他命令所改動的情況下執行并生效,否則該事務被打斷(abort)。 | ?>= 1.2.0 | 事務塊內所有命令的時間復雜度的總和 | 事務塊內所有命令的返回值,按命令執行的先后順序排列。 ??? 當操作被打斷時,返回空值 nil 。 |
DISCARD | 取消事務,放棄執行事務塊內的所有命令。 如果正在使用 WATCH 命令監視某個(或某些) key,那么取消所有監視,等同于執行命令 UNWATCH 。 | >= 2.0.0 | O(1) | 總是返回 OK 。 |
UNWATCH | 取消 WATCH 命令對所有 key 的監視。 如果在執行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被執行了的話,那么就不需要再執行 UNWATCH 了。 因為 EXEC 命令會執行事務,因此 WATCH 命令的效果已經產生了;而 DISCARD 命令在取消事務的同時也會取消所有對 key 的監視,因此這兩個命令執行之后,就沒有必要執行 UNWATCH 了。 | >= 2.2.0 | O(1) | 總是 OK 。 |
上面,自己僅僅進行了整理,沒什么好說的。重點是演練
2.命令演練
2.1MULTI ,起聲明事務的意思。表示“下面的命令,打個包做個整體”但不絕對。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 127.0.0.1:6379>?incr?bar (integer)?1 127.0.0.1:6379>?incr?foo (integer)?1 #事務開始 127.0.0.1:6379>?multi OK #發出的命令,直接返回QUEUED,放入隊列,不立即執行 127.0.0.1:6379>?incr?bar QUEUED 127.0.0.1:6379>?incr?foo QUEUED #執行所有事務塊內的命令 127.0.0.1:6379>? exec 1)?(integer)?2 2)?(integer)?2 #演示語法出錯情況,直接停止事務 127.0.0.1:6379>?incr?bar QUEUED 127.0.0.1:6379>?incrbar (error)?ERR?unknown? command ?'incrbar' 127.0.0.1:6379>? exec (error)?EXECABORT?Transaction?discarded?because?of?previous?errors. #事務不允許連續聲明 127.0.0.1:6379>?multi OK 127.0.0.1:6379>?multi (error)?ERR?MULTI?calls?can?not?be?nested #演示命令參數不匹配,部分成功 127.0.0.1:6379>?multi OK 127.0.0.1:6379>?incr?bar QUEUED 127.0.0.1:6379>?lpush?bar? "value2" QUEUED 127.0.0.1:6379>? exec 1)?(integer)?2 2)?(error)?WRONGTYPE?Operation?against?a?key?holding?the?wrong?kind?of?value |
結論
multi:不支持嵌套
redis對事務的支持,不嚴謹。不太符合ACID中的原子性。
Redis 在事務失敗時不進行回滾,而是繼續執行余下的命令”
如果你有使用關系式數據庫的經驗, 那么 “Redis 在事務失敗時不進行回滾,而是繼續執行余下的命令”這種做法可能會讓你覺得有點奇怪。
以下是這種做法的優點:
redis實踐?Redis 命令只會因為錯誤的語法而失敗(并且這些問題不能在入隊時發現),或是命令用在了錯誤類型的鍵上面:這也就是說,從實用性的角度來說,失敗的命令是由編程錯誤造成的,而這些錯誤應該在開發的過程中被發現,而不應該出現在生產環境中。
因為不需要對回滾進行支持,所以 Redis 的內部可以保持簡單且快速。
2.discard,"丟棄”意思。表示“上面的命令,統統都不要了”有點rollback的影子,但又不是。discard的意思,是把隊列中的命令舍棄掉,這時候還沒有發出命令。
1 2 3 4 5 6 7 8 9 10 11 12 | 127.0.0.1:6379>?multi OK 127.0.0.1:6379>?discard OK 127.0.0.1:6379>?multi OK 127.0.0.1:6379>?incr?bar QUEUED 127.0.0.1:6379>?incr?foo QUEUED 127.0.0.1:6379>?discard OK |
2.1 WATCH :含義“監視”。表示“這是我的菜,其他人靠邊站”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 127.0.0.1:6379>?flushdb OK 127.0.0.1:6379>?multi OK #watch命令不能在事務里出現,否則ERR 127.0.0.1:6379>? watch ?bar (error)?ERR?WATCH?inside?MULTI?is?not?allowed #監控bar,bar不再是隨便的key了,不允許隨便修改了。 127.0.0.1:6379>? watch ?bar OK #事務之前,沒有修改bar,事務成功 127.0.0.1:6379>?multi OK 127.0.0.1:6379>?incr?bar QUEUED 127.0.0.1:6379>? exec 1)?(integer)?1 #exec,將watch?打斷,重新watch 127.0.0.1:6379>? watch ?bar OK ##事務之前,修改bar,事務失敗 127.0.0.1:6379>?incr?bar (integer)?2 127.0.0.1:6379>?multi OK 127.0.0.1:6379>?incr?bar QUEUED 127.0.0.1:6379>? exec (nil) |
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态