亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

一篇文章帶你徹底搞懂Redis?事務(wù)

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

Redis 事務(wù)簡介

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

Redis 事務(wù)基本指令

Redis 提供了如下幾個事務(wù)相關(guān)的基礎(chǔ)指令。

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

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

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

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

實(shí)例分析

下面我們來通過一些實(shí)際具體例子,來體會下 Redis 中的事務(wù)。前面我們也說到 Redis 的事務(wù)不是正真的事務(wù),是無法完全滿足標(biāo)準(zhǔn)事務(wù)的ACID特性的。通過下面的例子,我們來看看,Redis 的“破產(chǎn)版”事務(wù)到底存在什么問題。

[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"

開啟事務(wù)后,提交的命令都會加入隊(duì)列(QUEUED),執(zhí)行 EXEC 后會逐步執(zhí)行命令并返回結(jié)果。這個看起來是不是和我們平時使用 MySQL 的事務(wù)操作相似,類似 start transaction 和 commit。

[B]正常取消事務(wù)

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)

開啟事務(wù)后,若不想繼續(xù)事務(wù),使用 DISCARD 取消,前面提交的命令并不會真正執(zhí)行,相關(guān)的 key 值不變。這個看起來也和 MySQL 的事務(wù)相似,類似 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"

在開啟事務(wù)之前 WATCH 了 a 的值,隨后再開啟事務(wù)。在另一個線程中設(shè)置了 a 的值(SET a 2),然后再 EXEC 執(zhí)行事務(wù),結(jié)果為 nil,
說明事務(wù)沒有被執(zhí)行。因?yàn)?a 的值在 WATCH 之后發(fā)生了變化,所以事務(wù)被取消了。

需要注意的是,這里和開啟事務(wù)的時間點(diǎn)沒有關(guān)系,與 MULTI 和另一個線程設(shè)置 a 的值的先后沒有關(guān)系。只要是在 WATCH 之后發(fā)生了變化。無論事務(wù)是否已經(jīng)開啟,執(zhí)行事務(wù)(EXEC)的時候都會取消。
普通情況下,在執(zhí)行 EXEC 和 DISCARD 命令時,都會默認(rèn)執(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"

當(dāng) Redis 開啟一個事務(wù)后,若添加的命令中有語法錯誤,會導(dǎo)致事務(wù)提交失敗。這種情況下事務(wù)隊(duì)列中的命令都不會被執(zhí)行。如上面例子中 a 和 b 的值都是原有的值。
這類在 EXEC 之前產(chǎn)生的錯誤,如命令名稱錯誤,命令參數(shù)錯誤等,會在 EXEC 執(zhí)行之前被檢測出來,所以在發(fā)生這些錯誤的時候,事務(wù)會被取消,事務(wù)中的所有命令都不會執(zhí)行。(這種情況看起來是不是有點(diǎn)像回滾了)

[E]運(yùn)行時錯誤

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"

當(dāng) Redis 開啟一個事務(wù)后,添加的命令沒有出現(xiàn)前面說的語法錯誤,但是在運(yùn)行時檢測到了類型錯誤,導(dǎo)致事務(wù)最提交失?。ㄕf未完全成功可能更準(zhǔn)確點(diǎn))。此時事務(wù)并不會回滾,而是跳過錯誤命令繼續(xù)執(zhí)行。
如上面的例子,未報(bào)錯的命令值已經(jīng)修改,a 被設(shè)置成了 1,b 被設(shè)置為了 hello,但是報(bào)錯的值未被修改,即 INCR b 類型錯誤,并未執(zhí)行,b 的值也沒有被再更新。

Redis 事務(wù)與 ACID

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

原子性(A)

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

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

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

EXEC 執(zhí)行之前,入隊(duì)報(bào)錯(實(shí)例分析中的語法錯誤)

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

EXEC 執(zhí)行之后,實(shí)際執(zhí)行時報(bào)錯(實(shí)例分析中的運(yùn)行時錯誤)

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

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

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

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

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

持久性(D)

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

關(guān)于 Redis 在開啟持久化之后,為啥還會丟失數(shù)據(jù),筆者會單獨(dú)整理一篇 Redis 持久化與主從相關(guān)的文章來介紹,此處簡單說下。
如果配置了 RDB 模式,在一個事務(wù)執(zhí)行后,下一次 RDB 快照還未執(zhí)行前,Redis 實(shí)例發(fā)生了宕機(jī),數(shù)據(jù)就會丟失、
如果配置了 AOF 模式,而 AOF 模式的三種配置選項(xiàng) no,everysec,always 也都可能會產(chǎn)生數(shù)據(jù)丟失的情況。

總結(jié)一下,Redis 事務(wù)對 ACID 的支持情況:

具備一定的原子性,但不支持回滾 滿足一致性 滿足隔離性 無法保證持久性 Redis 事務(wù)為什么不支持回滾

看一下官網(wǎng)的的說明:

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.

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

總結(jié)

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

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

相關(guān)文章

  • Redis swap空間(虛擬內(nèi)存)的使用詳解

    Redis swap空間(虛擬內(nèi)存)的使用詳解

    這篇文章主要介紹了Redis swap空間的使用示例,幫助大家更好的理解和學(xué)習(xí)使用Redis數(shù)據(jù)庫,感興趣的朋友可以了解下
    2021-03-03
  • Redis+threading實(shí)現(xiàn)多線程消息隊(duì)列的使用示例

    Redis+threading實(shí)現(xiàn)多線程消息隊(duì)列的使用示例

    Redis多線程消息隊(duì)列是一種使用Redis作為存儲后端的消息隊(duì)列實(shí)現(xiàn),它利用Redis的線程并發(fā)處理能力來提高消息隊(duì)列的處理效率,本文主要介紹了Redis+threading實(shí)現(xiàn)多線程消息隊(duì)列的使用示例,感興趣的可以了解一下
    2023-12-12
  • 緩存替換策略及應(yīng)用(以Redis、InnoDB為例)

    緩存替換策略及應(yīng)用(以Redis、InnoDB為例)

    本文以Redis、InnoDB為例給大家講解緩存替換策略及應(yīng)用,本文給大家提到五種置換策略,通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-07-07
  • redis的string類型及bitmap介紹

    redis的string類型及bitmap介紹

    這篇文章主要介紹了redis的string類型及bitmap介紹,redis有很多的客戶端連接進(jìn)來,站在redis所在機(jī)器的角度來說,就是有很多socket的連接
    2022-07-07
  • Redis查看KEY的數(shù)據(jù)類型的方法和步驟

    Redis查看KEY的數(shù)據(jù)類型的方法和步驟

    在Redis中,可以使用 TYPE 命令來查看指定key的數(shù)據(jù)類型,該命令會返回存儲在指定key中的值的數(shù)據(jù)類型,本文給大家介紹了具體的使用方法和步驟,感興趣的朋友可以參考下
    2024-04-04
  • Redis高并發(fā)情況下并發(fā)扣減庫存項(xiàng)目實(shí)戰(zhàn)

    Redis高并發(fā)情況下并發(fā)扣減庫存項(xiàng)目實(shí)戰(zhàn)

    本文主要介紹了Redis高并發(fā)情況下并發(fā)扣減庫存項(xiàng)目實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 通過實(shí)例解析布隆過濾器工作原理及實(shí)例

    通過實(shí)例解析布隆過濾器工作原理及實(shí)例

    這篇文章主要介紹了通過實(shí)例解析布隆過濾器工作原理及實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • python腳本實(shí)現(xiàn)Redis未授權(quán)批量提權(quán)

    python腳本實(shí)現(xiàn)Redis未授權(quán)批量提權(quán)

    這篇文章主要給大家介紹了關(guān)于利用python腳本實(shí)現(xiàn)redis未授權(quán)批量提權(quán)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • Redis+Caffeine實(shí)現(xiàn)多級緩存的步驟

    Redis+Caffeine實(shí)現(xiàn)多級緩存的步驟

    隨著不斷的發(fā)展,這一架構(gòu)也產(chǎn)生了改進(jìn),在一些場景下可能單純使用Redis類的遠(yuǎn)程緩存已經(jīng)不夠了,還需要進(jìn)一步配合本地緩存使用,例如Guava cache或Caffeine,從而再次提升程序的響應(yīng)速度與服務(wù)性能,這篇文章主要介紹了Redis+Caffeine實(shí)現(xiàn)多級緩存,需要的朋友可以參考下
    2024-01-01
  • Redis正確使用的十個技巧

    Redis正確使用的十個技巧

    Redis已經(jīng)走過了很長的一段路,隨之而來的一系列最佳實(shí)踐,使得大多數(shù)人可以正確地使用Redis,下面我們將探索正確使用 Redis 的10個技巧。
    2015-10-10

最新評論