最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一篇文章帶你徹底搞懂Redis?事務

 更新時間:2022年10月31日 08:28:39   作者:MaxFang  
這篇文章主要介紹了一篇文章帶你徹底搞懂Redis?事務的相關資料,需要的朋友可以參考下

Redis 事務簡介

Redis 只是提供了簡單的事務功能。其本質是一組命令的集合,事務支持一次執(zhí)行多個命令,在事務執(zhí)行過程中,會順序執(zhí)行隊列中的命令,其他客戶端提交的命令請求不會插入到本事務執(zhí)行命令序列中。命令的執(zhí)行過程是順序執(zhí)行的,但不能保證原子性。無法像 MySQL 那樣,有隔離級別,出了問題之后還能回滾數據等高級操作。后面會詳細分析。

Redis 事務基本指令

Redis 提供了如下幾個事務相關的基礎指令。

MULTI開啟事務,Redis 會將后續(xù)命令加到隊列中,而不真正執(zhí)行它們,直到后續(xù)使用EXEC來原子化的順序執(zhí)行這些命令 EXEC執(zhí)行所有事務塊內的命令 DISCARD取消事務,放棄執(zhí)行事務塊內所有的命令 WATCH監(jiān)視一個或多個 key,若事務在執(zhí)行前,這些 key 被其他命令修改,則事務被終端,不會執(zhí)行事務中的任何命令 UNWATCH取消 WATCH命令對所有 keys 的監(jiān)視

一般情況下,一個簡單的 Redis 事務主要分為如下幾個部分:

執(zhí)行命令MULTI開啟一個事務。 開啟事務之后,執(zhí)行命令的多個命令會依次被放入一個隊列,放入成功則會返回QUEUED消息。 執(zhí)行命令EXEC提交事務,Redis 會依次執(zhí)行隊列中的命令,并依次返回所有命令的結果。(若想放棄提交事務,則執(zhí)行DISCARD)。

下圖簡單介紹了下 Redis 事務執(zhí)行的過程:

實例分析

下面我們來通過一些實際具體例子,來體會下 Redis 中的事務。前面我們也說到 Redis 的事務不是正真的事務,是無法完全滿足標準事務的ACID特性的。通過下面的例子,我們來看看,Redis 的“破產版”事務到底存在什么問題。

[A]正常執(zhí)行提交

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),執(zhí)行 EXEC 后會逐步執(zhí)行命令并返回結果。這個看起來是不是和我們平時使用 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)

開啟事務后,若不想繼續(xù)事務,使用 DISCARD 取消,前面提交的命令并不會真正執(zhí)行,相關的 key 值不變。這個看起來也和 MySQL 的事務相似,類似 start transaction 和 rollback。

[C]WATCH 監(jiān)視 key

-- 線程 1 中執(zhí)行
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 中執(zhí)行
----------------------------------------- 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 執(zhí)行事務,結果為 nil,
說明事務沒有被執(zhí)行。因為 a 的值在 WATCH 之后發(fā)生了變化,所以事務被取消了。

需要注意的是,這里和開啟事務的時間點沒有關系,與 MULTI 和另一個線程設置 a 的值的先后沒有關系。只要是在 WATCH 之后發(fā)生了變化。無論事務是否已經開啟,執(zhí)行事務(EXEC)的時候都會取消。
普通情況下,在執(zhí)行 EXEC 和 DISCARD 命令時,都會默認執(zhí)行 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 開啟一個事務后,若添加的命令中有語法錯誤,會導致事務提交失敗。這種情況下事務隊列中的命令都不會被執(zhí)行。如上面例子中 a 和 b 的值都是原有的值。
這類在 EXEC 之前產生的錯誤,如命令名稱錯誤,命令參數錯誤等,會在 EXEC 執(zhí)行之前被檢測出來,所以在發(fā)生這些錯誤的時候,事務會被取消,事務中的所有命令都不會執(zhí)行。(這種情況看起來是不是有點像回滾了)

[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 開啟一個事務后,添加的命令沒有出現前面說的語法錯誤,但是在運行時檢測到了類型錯誤,導致事務最提交失?。ㄕf未完全成功可能更準確點)。此時事務并不會回滾,而是跳過錯誤命令繼續(xù)執(zhí)行。
如上面的例子,未報錯的命令值已經修改,a 被設置成了 1,b 被設置為了 hello,但是報錯的值未被修改,即 INCR b 類型錯誤,并未執(zhí)行,b 的值也沒有被再更新。

Redis 事務與 ACID

通過上面的例子,我們已經知道 Redis 的事務和我們通常接觸的 MySQL 等關系數據庫的事務還有有一定差異的。它不保證原子性。同時 Redis 事務也沒有事務隔離級別的概念。下面我們來具體看下 Redis 在 ACID 四個特性中,那些是滿足的,那些是不滿足的。
事務執(zhí)行可以分為命令入隊(EXEC 執(zhí)行前)和命令實際執(zhí)行(EXEC 執(zhí)行之后)兩個階段。下面我們在分析的時候,很多時候都會分這兩種情況來分析。

原子性(A)

上面的實例分析中,[A],[B],[C]三種正常的情況,我們可以很明顯的看出,是保證了原子性的。
但是一些異常情況下,是不滿足原子性的。

如 [D] 所示的情況,客戶端發(fā)送的命令有語法錯誤,在命令入隊列時 Redis 就判斷出來了。等到執(zhí)行 EXEC 命令時,Redis 就會拒絕執(zhí)行所有提交的命令,返回事務失敗的結果。此種情況下,事務中的所有命令都不會被執(zhí)行了,是保證了原子性的。 如 [E] 所示的情況,事務操作入隊時,命令和操作類型不匹配,此時 Redis 沒有檢查出錯誤(這類錯誤是運行時錯誤)。等到執(zhí)行 EXEC 命令后,Redis 實際執(zhí)行這些命令操作時,就會報錯。需要注意的是,雖然 Redis 會對錯誤的命令報錯不執(zhí)行,但是其余正確的命令會依次執(zhí)行完。此種情況下,是無法保證原子性的。 在執(zhí)行事務的 EXEC 命令時,Redis 實例發(fā)生了故障,導致事務執(zhí)行失敗。此時,如果開啟了 AOF 日志,那么只會有部分事務操作被記錄到 AOF 日志中。使用redis-check-aof工具檢測 AOF 日志文件,可以把未完成的事務操作從 AOF 文件中去除。這樣一來,使用 AOF 文件恢復實例后,事務操作不會被再執(zhí)行,從而保證了原子性。若使用的 RDB 模式,最新的 RDB 快照是在 EXEC 執(zhí)行之前生成的,使用快照恢復之后,事務中的命令也都沒有執(zhí)行,從而保證了原子性。若 Redis 沒有開啟持久化,則重啟后內存中的數據全部丟失,也就談不上原子性了。 一致性(C)

一致性指的是事務執(zhí)行前后,數據符合數據庫的定義和要求。這點在 Redis 事務中是滿足的,不論是發(fā)生語法錯誤還是運行時錯誤,錯誤的命令均不會被執(zhí)行。

EXEC 執(zhí)行之前,入隊報錯(實例分析中的語法錯誤)

事務會放棄執(zhí)行,故可以保證一致性。

EXEC 執(zhí)行之后,實際執(zhí)行時報錯(實例分析中的運行時錯誤)

錯誤的命令不會被執(zhí)行,正確的命令被執(zhí)行,一致性可以保證。

EXEC 執(zhí)行時,實例宕機

若 Redis 沒有開啟持久化,實例宕機重啟后,數據都沒有了,數據是一致的。
若配置了 RDB 方式,RDB 快照不會在事務執(zhí)行時執(zhí)行。所以,若事務執(zhí)行到一半,實例發(fā)生了故障,此時上一次 RDB 快照中不會包含事務所做的修改,而下一次 RDB 快照還沒有執(zhí)行,實例重啟后,事務修改的數據會丟失,數據是一致的。若事務已經完成,但新一次的 RDB 快照還沒有生成,那事務修改的數據也會丟失,數據也是一致的。
若配置了 AOF 方式。當事務操作還沒被記錄到 AOF 日志時,實例就發(fā)生故障了,使用 AOF 日志恢復后數據是一致的。若事務中的只有部分操作被記錄到 AOF 日志,可以使用 redis-check-aof清除事務中已經完成的操作,數據庫恢復后數據也是一致的。

隔離性(I) 并發(fā)操作在 EXEC 執(zhí)行前,隔離性需要通過 WATCH 機制來保證 并發(fā)操作在 EXEC 命令之后,隔離性可以保證

情況 a 可以參考前面的實例分析 WATCH 命令的使用。
情況 b,由于 Redis 是單線程執(zhí)行命令,EXEC 命令執(zhí)行后,Redis 會保證先把事務隊列中的所有命令執(zhí)行完之后再執(zhí)行之后的命令。

持久性(D)

若 Redis 沒有開啟持久化,那么就是所有數據都存儲在內存中,一旦重啟,數據就會丟失,因此此時事務的持久性是肯定無法得到保證的。
若 Redis 開啟了持久化,當實例宕機重啟,還是會有可能丟失數據,因此也并能完全保證持久性。
因此,我們可以說 Redis 事務無法一定保證持久性,僅在特殊的情況下,可以保證持久性。

關于 Redis 在開啟持久化之后,為啥還會丟失數據,筆者會單獨整理一篇 Redis 持久化與主從相關的文章來介紹,此處簡單說下。
如果配置了 RDB 模式,在一個事務執(zhí)行后,下一次 RDB 快照還未執(zhí)行前,Redis 實例發(fā)生了宕機,數據就會丟失、
如果配置了 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.

大部分需要事務回滾的情況是程序錯誤導致的,這種情況一般是開發(fā)環(huán)境,生產環(huán)境不應該出現這種錯誤。
對于邏輯錯誤,例如應該加 1,結果寫成了加 2,這種情況無法通過回滾來解決。
Redis 追求的是簡單高效,而傳統事務的實現相對復雜很多,這和 Redis 的設計思想是違背的。當我們享受 Redis 的快速時,也就無法再要求它更多。

總結

本文主要介紹了 Redis 事務的基礎指令與執(zhí)行流程,并分析了其對傳統 ACID 特性支持的情況,相信大家對 Redis 事務已經有了一個簡單的了解。
通過上面的介紹,會發(fā)現 Redis 的事務似乎有點雞肋,確實實際中也很少會使用。至于事務的具體實現,筆者后續(xù)文章會結合源碼進行分析。今天的文章就到這里,下期我們接著學。

到此這篇關于一篇文章帶你徹底搞懂Redis 事務的文章就介紹到這了,更多相關Redis 事務內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Redis key鍵的具體使用

    Redis key鍵的具體使用

    Redis 是一種鍵值(key-value)型的緩存型數據庫,它將數據全部以鍵值對的形式存儲在內存中,本文就來介紹一下key鍵的具體使用,感興趣的可以了解一下
    2024-02-02
  • Redis?腳本和連接命令示例詳解

    Redis?腳本和連接命令示例詳解

    Redis腳本是一種可以實現復雜任務的腳本語言,可以用來快速履行復雜任務,靈活處理數據管理和管理復雜的利用場景,這篇文章主要介紹了Redis?腳本和連接命令,需要的朋友可以參考下
    2023-09-09
  • Redis SETEX命令實現鍵值對管理

    Redis SETEX命令實現鍵值對管理

    本文主要介紹了Redis SETEX命令實現鍵值對管理,SETEX命令用于設置具有過期時間的鍵值對,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-06-06
  • Redis教程(四):Hashes數據類型

    Redis教程(四):Hashes數據類型

    這篇文章主要介紹了Redis教程(四):Hashes數據類型,本文講解了Hashes數據類型概述、相關命令列表和命令使用示例等內容,需要的朋友可以參考下
    2015-04-04
  • 詳解redis在服務器linux下啟動的相關命令(安裝和配置)

    詳解redis在服務器linux下啟動的相關命令(安裝和配置)

    這篇文章主要介紹了redis在服務器linux下的啟動的相關命令(安裝和配置),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • Redis主從復制詳解

    Redis主從復制詳解

    今天小編就為大家分享一篇關于Redis主從復制詳解,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • RedisTemplate 實現基于Value 操作的簡易鎖機制(示例代碼)

    RedisTemplate 實現基于Value 操作的簡易鎖機制(示例代碼)

    本文將介紹如何使用 RedisTemplate 的 opsForValue().setIfAbsent() 方法來實現一種簡單的鎖機制,并提供一個示例代碼,展示如何在 Java 應用中利用這一機制來保護共享資源的訪問,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • Redis實現多人多聊天室功能

    Redis實現多人多聊天室功能

    這篇文章主要為大家詳細介紹了Redis實現多人多聊天室功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • redis和redisson實現分布式鎖的操作方法

    redis和redisson實現分布式鎖的操作方法

    使用 Redis 實現分布式鎖,最直接的想法是利用 setnx 和 expire 命令實現加鎖,這篇文章主要介紹了redis和redisson實現分布式鎖的操作方法,需要的朋友可以參考下
    2024-03-03
  • Redis底層數據結構之dict、ziplist、quicklist詳解

    Redis底層數據結構之dict、ziplist、quicklist詳解

    本文給大家詳細介紹了Redis的底層數據結構:dict、ziplist、quicklist的相關知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-09-09

最新評論

文山县| 易门县| 光山县| 青阳县| 余庆县| 衡南县| 奉节县| 鹤山市| 鱼台县| 宁国市| 西青区| 苗栗县| 泾阳县| 安阳市| 凌海市| 阿勒泰市| 甘孜| 秭归县| 社旗县| 光泽县| 辽源市| 高陵县| 平度市| 张家口市| 横峰县| 晋州市| 宜都市| 汶上县| 洛浦县| 诸城市| 西吉县| 仪征市| 龙州县| 酉阳| 崇明县| 白玉县| 葵青区| 苏州市| 新邵县| 安顺市| 临夏市|