<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Redis 只是提供了簡單的事務功能。其本質是一組命令的集合,事務支援一次執行多個命令,在事務執行過程中,會順序執行佇列中的命令,其他使用者端提交的命令請求不會插入到本事務執行命令序列中。命令的執行過程是順序執行的,但不能保證原子性。無法像 MySQL 那樣,有隔離級別,出了問題之後還能回滾資料等高階操作。後面會詳細分析。
Redis 提供瞭如下幾個事務相關的基礎指令。
MULTI
開啟事務,Redis 會將後續命令加到佇列中,而不真正執行它們,直到後續使用EXEC
來原子化的順序執行這些命令 EXEC
執行所有事務塊內的命令 DISCARD
取消事務,放棄執行事務塊內所有的命令 WATCH
監視一個或多個 key,若事務在執行前,這些 key 被其他命令修改,則事務被終端,不會執行事務中的任何命令 UNWATCH
取消 WATCH
命令對所有 keys 的監視
一般情況下,一個簡單的 Redis 事務主要分為如下幾個部分:
執行命令MULTI
開啟一個事務。 開啟事務之後,執行命令的多個命令會依次被放入一個佇列,放入成功則會返回QUEUED
訊息。 執行命令EXEC
提交事務,Redis 會依次執行佇列中的命令,並依次返回所有命令的結果。(若想放棄提交事務,則執行DISCARD
)。
下圖簡單介紹了下 Redis 事務執行的過程:
下面我們來通過一些實際具體例子,來體會下 Redis 中的事務。前面我們也說到 Redis 的事務不是正真的事務,是無法完全滿足標準事務的ACID
特性的。通過下面的例子,我們來看看,Redis 的“破產版”事務到底存在什麼問題。
[A]正常執行提交
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET a 1 QUEUED 127.0.0.1:6379> SET b 2 QUEUED 127.0.0.1:6379> EXEC 1) OK 2) OK 127.0.0.1:6379> GET a "1" 127.0.0.1:6379> GET b "2"
開啟事務後,提交的命令都會加入佇列(QUEUED),執行 EXEC 後會逐步執行命令並返回結果。這個看起來是不是和我們平時使用 MySQL 的事務操作相似,類似 start transaction 和 commit。
[B]正常取消事務
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET a 1 QUEUED 127.0.0.1:6379> SET b 2 QUEUED 127.0.0.1:6379> DISCARD OK 127.0.0.1:6379> 127.0.0.1:6379> GET a (nil) 127.0.0.1:6379> GET b (nil)
開啟事務後,若不想繼續事務,使用 DISCARD 取消,前面提交的命令並不會真正執行,相關的 key 值不變。這個看起來也和 MySQL 的事務相似,類似 start transaction 和 rollback。
[C]WATCH 監視 key
-- 執行緒 1 中執行 127.0.0.1:6379> del a (integer) 1 127.0.0.1:6379> get a (nil) 127.0.0.1:6379> SET a 0 OK 127.0.0.1:6379> WATCH a OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET a 1 QUEUED ----------------------------------------- 執行緒 2 中執行 ----------------------------------------- 127.0.0.1:6379> SET a 2 ----------------------------------------- OK 127.0.0.1:6379> EXEC (nil) 127.0.0.1:6379> GET a "2"
在開啟事務之前 WATCH 了 a 的值,隨後再開啟事務。在另一個執行緒中設定了 a 的值(SET a 2),然後再 EXEC 執行事務,結果為 nil,
說明事務沒有被執行。因為 a 的值在 WATCH 之後發生了變化,所以事務被取消了。
需要注意的是,這裡和開啟事務的時間點沒有關係,與 MULTI 和另一個執行緒設定 a 的值的先後沒有關係。只要是在 WATCH 之後發生了變化。無論事務是否已經開啟,執行事務(EXEC)的時候都會取消。
普通情況下,在執行 EXEC 和 DISCARD 命令時,都會預設執行 UNWATCH。
[D]語法錯誤
127.0.0.1:6379> SET a 1 OK 127.0.0.1:6379> SET b 2 OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET a 11 QUEUED 127.0.0.1:6379> SETS b 22 (error) ERR unknown command 'SETS' 127.0.0.1:6379> EXEC (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> GET a "1" 127.0.0.1:6379> GET b "2"
當 Redis 開啟一個事務後,若新增的命令中有語法錯誤,會導致事務提交失敗。這種情況下事務佇列中的命令都不會被執行。如上面例子中 a 和 b 的值都是原有的值。
這類在 EXEC 之前產生的錯誤,如命令名稱錯誤,命令引數錯誤等,會在 EXEC 執行之前被檢測出來,所以在發生這些錯誤的時候,事務會被取消,事務中的所有命令都不會執行。(這種情況看起來是不是有點像回滾了)
[E]執行時錯誤
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET a 1 QUEUED 127.0.0.1:6379> SET b hello QUEUED 127.0.0.1:6379> INCR b QUEUED 127.0.0.1:6379> EXEC 1) OK 2) OK 3) (error) ERR value is not an integer or out of range 127.0.0.1:6379> GET a "1" 127.0.0.1:6379> GET b "hello"
當 Redis 開啟一個事務後,新增的命令沒有出現前面說的語法錯誤,但是在執行時檢測到了型別錯誤,導致事務最提交失敗(說未完全成功可能更準確點)。此時事務並不會回滾,而是跳過錯誤命令繼續執行。
如上面的例子,未報錯的命令值已經修改,a 被設定成了 1,b 被設定為了 hello,但是報錯的值未被修改,即 INCR b 型別錯誤,並未執行,b 的值也沒有被再更新。
通過上面的例子,我們已經知道 Redis 的事務和我們通常接觸的 MySQL 等關聯式資料庫的事務還有有一定差異的。它不保證原子性。同時 Redis 事務也沒有事務隔離級別的概念。下面我們來具體看下 Redis 在 ACID 四個特性中,那些是滿足的,那些是不滿足的。
事務執行可以分為命令入隊(EXEC 執行前)和命令實際執行(EXEC 執行之後)兩個階段。下面我們在分析的時候,很多時候都會分這兩種情況來分析。
原子性(A)
上面的範例分析中,[A],[B],[C]三種正常的情況,我們可以很明顯的看出,是保證了原子性的。
但是一些異常情況下,是不滿足原子性的。
如 [D] 所示的情況,使用者端傳送的命令有語法錯誤,在命令入佇列時 Redis 就判斷出來了。等到執行 EXEC 命令時,Redis 就會拒絕執行所有提交的命令,返回事務失敗的結果。此種情況下,事務中的所有命令都不會被執行了,是保證了原子性的。 如 [E] 所示的情況,事務操作入隊時,命令和操作型別不匹配,此時 Redis 沒有檢查出錯誤(這類錯誤是執行時錯誤)。等到執行 EXEC 命令後,Redis 實際執行這些命令操作時,就會報錯。需要注意的是,雖然 Redis 會對錯誤的命令報錯不執行,但是其餘正確的命令會依次執行完。此種情況下,是無法保證原子性的。 在執行事務的 EXEC 命令時,Redis 範例發生了故障,導致事務執行失敗。此時,如果開啟了 AOF 紀錄檔,那麼只會有部分事務操作被記錄到 AOF 紀錄檔中。使用redis-check-aof
工具檢測 AOF 紀錄檔檔案,可以把未完成的事務操作從 AOF 檔案中去除。這樣一來,使用 AOF 檔案恢復範例後,事務操作不會被再執行,從而保證了原子性。若使用的 RDB 模式,最新的 RDB 快照是在 EXEC 執行之前生成的,使用快照恢復之後,事務中的命令也都沒有執行,從而保證了原子性。若 Redis 沒有開啟持久化,則重啟後記憶體中的資料全部丟失,也就談不上原子性了。 一致性(C)
一致性指的是事務執行前後,資料符合資料庫的定義和要求。這點在 Redis 事務中是滿足的,不論是發生語法錯誤還是執行時錯誤,錯誤的命令均不會被執行。
EXEC 執行之前,入隊報錯(範例分析中的語法錯誤)
事務會放棄執行,故可以保證一致性。
EXEC 執行之後,實際執行時報錯(範例分析中的執行時錯誤)
錯誤的命令不會被執行,正確的命令被執行,一致性可以保證。
EXEC 執行時,範例宕機
若 Redis 沒有開啟持久化,範例宕機重啟後,資料都沒有了,資料是一致的。
若設定了 RDB 方式,RDB 快照不會在事務執行時執行。所以,若事務執行到一半,範例發生了故障,此時上一次 RDB 快照中不會包含事務所做的修改,而下一次 RDB 快照還沒有執行,範例重啟後,事務修改的資料會丟失,資料是一致的。若事務已經完成,但新一次的 RDB 快照還沒有生成,那事務修改的資料也會丟失,資料也是一致的。
若設定了 AOF 方式。當事務操作還沒被記錄到 AOF 紀錄檔時,範例就發生故障了,使用 AOF 紀錄檔恢復後資料是一致的。若事務中的只有部分操作被記錄到 AOF 紀錄檔,可以使用 redis-check-aof
清除事務中已經完成的操作,資料庫恢復後資料也是一致的。
隔離性(I) 並行操作在 EXEC 執行前,隔離性需要通過 WATCH 機制來保證 並行操作在 EXEC 命令之後,隔離性可以保證
情況 a 可以參考前面的範例分析 WATCH 命令的使用。
情況 b,由於 Redis 是單執行緒執行命令,EXEC 命令執行後,Redis 會保證先把事務佇列中的所有命令執行完之後再執行之後的命令。
永續性(D)
若 Redis 沒有開啟持久化,那麼就是所有資料都儲存在記憶體中,一旦重啟,資料就會丟失,因此此時事務的永續性是肯定無法得到保證的。
若 Redis 開啟了持久化,當範例宕機重啟,還是會有可能丟失資料,因此也並能完全保證永續性。
因此,我們可以說 Redis 事務無法一定保證永續性,僅在特殊的情況下,可以保證永續性。
關於 Redis 在開啟持久化之後,為啥還會丟失資料,筆者會單獨整理一篇 Redis 持久化與主從相關的文章來介紹,此處簡單說下。
如果設定了 RDB 模式,在一個事務執行後,下一次 RDB 快照還未執行前,Redis 範例發生了宕機,資料就會丟失、
如果設定了 AOF 模式,而 AOF 模式的三種設定選項 no,everysec,always 也都可能會產生資料丟失的情況。
總結一下,Redis 事務對 ACID 的支援情況:
具備一定的原子性,但不支援回滾 滿足一致性 滿足隔離性 無法保證永續性 Redis 事務為什麼不支援回滾
看一下官網的的說明:
What about rollbacks?
Redis does not support rollbacks of transactions since supporting rollbacks would have a significant impact on the simplicity and performance of Redis.
大部分需要事務回滾的情況是程式錯誤導致的,這種情況一般是開發環境,生產環境不應該出現這種錯誤。
對於邏輯錯誤,例如應該加 1,結果寫成了加 2,這種情況無法通過回滾來解決。
Redis 追求的是簡單高效,而傳統事務的實現相對複雜很多,這和 Redis 的設計思想是違背的。當我們享受 Redis 的快速時,也就無法再要求它更多。
本文主要介紹了 Redis 事務的基礎指令與執行流程,並分析了其對傳統 ACID 特性支援的情況,相信大家對 Redis 事務已經有了一個簡單的瞭解。
通過上面的介紹,會發現 Redis 的事務似乎有點雞肋,確實實際中也很少會使用。至於事務的具體實現,筆者後續文章會結合原始碼進行分析。今天的文章就到這裡,下期我們接著學。
到此這篇關於一篇文章帶你徹底搞懂Redis 事務的文章就介紹到這了,更多相關Redis 事務內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45