欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

Redis 事務(wù)簡(jiǎn)介

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

Redis 事務(wù)基本指令

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

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

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

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

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

實(shí)例分析

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

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

開(kāi)啟事務(wù)后,提交的命令都會(huì)加入隊(duì)列(QUEUED),執(zhí)行 EXEC 后會(huì)逐步執(zhí)行命令并返回結(jié)果。這個(gè)看起來(lái)是不是和我們平時(shí)使用 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)

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

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

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

[D]語(yǔ)法錯(cuò)誤

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

[E]運(yùn)行時(shí)錯(cuò)誤

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

Redis 事務(wù)與 ACID

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

原子性(A)

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

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

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

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

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

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

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

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

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

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

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

持久性(D)

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

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

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

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

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

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

總結(jié)

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

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

相關(guān)文章

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

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

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

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

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

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

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

    redis的string類型及bitmap介紹

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

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

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

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

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

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

    這篇文章主要介紹了通過(guò)實(shí)例解析布隆過(guò)濾器工作原理及實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(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)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • Redis+Caffeine實(shí)現(xiàn)多級(jí)緩存的步驟

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

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

    Redis正確使用的十個(gè)技巧

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

最新評(píng)論