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

Redis事務(wù)處理的實(shí)現(xiàn)示例

 更新時(shí)間:2025年10月19日 11:35:52   作者:運(yùn)維開(kāi)發(fā)小白  
這篇文章主要介紹了Redis事務(wù)處理的實(shí)現(xiàn)示例,包括事務(wù)的原理、相關(guān)命令,如MULTI、EXEC、WATCH等、CAS樂(lè)觀鎖實(shí)現(xiàn)方式以及事務(wù)執(zhí)行步驟,感興趣的可以了解一下

歡迎繼續(xù)跟隨《Redis新手指南:從入門(mén)到精通》專欄的步伐!在本文中,我們將探討Redis的事務(wù)處理機(jī)制。了解如何使用事務(wù)來(lái)保證一系列操作的原子性和一致性,這對(duì)于構(gòu)建可靠的應(yīng)用程序至關(guān)重要

1 什么是Redis事務(wù)??

? Redis 事務(wù)的本質(zhì)是一組命令的集合。事務(wù)支持一次執(zhí)行多個(gè)命令,一個(gè)事務(wù)中所有命令都會(huì)被序列化。在事務(wù)執(zhí)行過(guò)程,會(huì)按照順序列化執(zhí)行隊(duì)列中的命令,其他客戶端提交的命令請(qǐng)求不會(huì)插入到事務(wù)執(zhí)行命令序列中

總結(jié)說(shuō):redis 事務(wù)就是一次性、順序性、排他性的執(zhí)行一個(gè)隊(duì)列中的一系列命令

2 Redis事務(wù)相關(guān)命令和使用??

MULTI、EXEC、DISCARD 和 WATCH 是 Redis 事務(wù)相關(guān)的命令

  • MULTI :開(kāi)啟事務(wù),redis會(huì)將后續(xù)的命令逐個(gè)放入隊(duì)列中,然后使用EXEC命令來(lái)原子化執(zhí)行這個(gè)命令系列。原子化執(zhí)行,它們要么全部執(zhí)行成功,要么全部回滾。
  • EXEC:執(zhí)行事務(wù)中的所有操作命令
  • DISCARD:取消事務(wù),放棄執(zhí)行事務(wù)塊中的所有命令
  • WATCH:監(jiān)視一個(gè)或多個(gè)key,如果事務(wù)在執(zhí)行前,這個(gè)key(或多個(gè)key)被其他命令修改,則事務(wù)被中斷,不會(huì)執(zhí)行事務(wù)中的任何命令
  • UNWATCH:取消WATCH對(duì)所有key的監(jiān)視

1.標(biāo)準(zhǔn)的事務(wù)執(zhí)行

給k1、k2分別賦值,在事務(wù)中修改k1、k2,執(zhí)行事務(wù)后,查看k1、k2值都被修改

127.0.0.1:6379[1]> set key1 value1
OK
127.0.0.1:6379[1]> set key2 value2
OK
127.0.0.1:6379[1]> multi # 開(kāi)啟事務(wù)
OK
127.0.0.1:6379[1](TX)> set key1 11
QUEUED
127.0.0.1:6379[1](TX)> set key2 22
QUEUED
127.0.0.1:6379[1](TX)> exec # 執(zhí)行事務(wù)中所有的操作命令
1) OK
2) OK
127.0.0.1:6379[1]> get key1
"11"
127.0.0.1:6379[1]> get key2
"22"

2.事務(wù)取消

127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1](TX)> set key1 111
QUEUED
127.0.0.1:6379[1](TX)> set key2 222
QUEUED
127.0.0.1:6379[1](TX)> DISCARD # 取消事務(wù)
OK
127.0.0.1:6379[1]> exec
(error) ERR EXEC without MULTI

3.事務(wù)出現(xiàn)錯(cuò)誤的處理

  • 語(yǔ)法錯(cuò)誤(編譯器錯(cuò)誤)

在開(kāi)啟事務(wù)后,修改k1值為11,k2值為22,但k2語(yǔ)法錯(cuò)誤,最終導(dǎo)致事務(wù)提交失敗,k1、k2保留原值

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 11
QUEUED
127.0.0.1:6379> sets k2 22
(error) ERR unknown command `sets`, with args beginning with: `k2`, `22`, 
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379>
  • Redis類型錯(cuò)誤(運(yùn)行時(shí)錯(cuò)誤)

? 在開(kāi)啟事務(wù)后,修改k1值為11,k2值為22,但將k2的類型作為L(zhǎng)ist,在運(yùn)行時(shí)檢測(cè)類型錯(cuò)誤,最終導(dǎo)致事務(wù)提交失敗,此時(shí)事務(wù)并沒(méi)有回滾,而是跳過(guò)錯(cuò)誤命令繼續(xù)執(zhí)行, 結(jié)果k1值改變、k2保留原值

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k1 v2
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 11
QUEUED
127.0.0.1:6379> lpush k2 22
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> get k1
"11"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379>

3 CAS操作實(shí)現(xiàn)樂(lè)觀鎖??

WATCH 命令可以為 Redis 事務(wù)提供 check-and-set (CAS)行為

  • CAS? 樂(lè)觀鎖?Redis官方的例子幫你理解

被 WATCH 的鍵會(huì)被監(jiān)視,并會(huì)發(fā)覺(jué)這些鍵是否被改動(dòng)過(guò)了。如果有至少一個(gè)被監(jiān)視的鍵在 EXEC 執(zhí)行之前被修改了, 那么整個(gè)事務(wù)都會(huì)被取消, EXEC 返回nil-reply來(lái)表示事務(wù)已經(jīng)失敗。

舉個(gè)例子, 假設(shè)我們需要原子性地為某個(gè)值進(jìn)行增 1 操作(假設(shè) INCR 不存在)。

首先我們可能會(huì)這樣做:

val = GET mykey
val = val + 1
SET mykey $val

上面的這個(gè)實(shí)現(xiàn)在只有一個(gè)客戶端的時(shí)候可以執(zhí)行得很好。但是, 當(dāng)多個(gè)客戶端同時(shí)對(duì)同一個(gè)鍵進(jìn)行這樣的操作時(shí), 就會(huì)產(chǎn)生競(jìng)爭(zhēng)條件。舉個(gè)例子, 如果客戶端 A 和 B 都讀取了鍵原來(lái)的值, 比如 10 , 那么兩個(gè)客戶端都會(huì)將鍵的值設(shè)為 11 , 但正確的結(jié)果應(yīng)該是 12 才對(duì)。

有了 WATCH ,我們就可以輕松地解決這類問(wèn)題了:

WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC

使用上面的代碼, 如果在 WATCH 執(zhí)行之后, EXEC 執(zhí)行之前, 有其他客戶端修改了 mykey 的值, 那么當(dāng)前客戶端的事務(wù)就會(huì)失敗。程序需要做的, 就是不斷重試這個(gè)操作, 直到?jīng)]有發(fā)生碰撞為止。

這種形式的鎖被稱作樂(lè)觀鎖, 它是一種非常強(qiáng)大的鎖機(jī)制。并且因?yàn)榇蠖鄶?shù)情況下, 不同的客戶端會(huì)訪問(wèn)不同的鍵, 碰撞的情況一般都很少, 所以通常并不需要進(jìn)行重試。

  • watch是如何監(jiān)視實(shí)現(xiàn)的呢?

Redis使用WATCH命令來(lái)決定事務(wù)是繼續(xù)執(zhí)行還是回滾,那就需要在MULTI之前使用WATCH來(lái)監(jiān)控某些鍵值對(duì),然后使用MULTI命令來(lái)開(kāi)啟事務(wù),執(zhí)行對(duì)數(shù)據(jù)結(jié)構(gòu)操作的各種命令,此時(shí)這些命令入隊(duì)列。

當(dāng)使用EXEC執(zhí)行事務(wù)時(shí),首先會(huì)比對(duì)WATCH所監(jiān)控的鍵值對(duì),如果沒(méi)發(fā)生改變,它會(huì)執(zhí)行事務(wù)隊(duì)列中的命令,提交事務(wù);如果發(fā)生變化,將不會(huì)執(zhí)行事務(wù)中的任何命令,同時(shí)事務(wù)回滾。當(dāng)然無(wú)論是否回滾,Redis都會(huì)取消執(zhí)行事務(wù)前的WATCH命令

  • watch 命令實(shí)現(xiàn)監(jiān)視

在事務(wù)開(kāi)始前用WATCH監(jiān)控k1,之后修改k1為11,說(shuō)明事務(wù)開(kāi)始前k1值被改變,MULTI開(kāi)始事務(wù),修改k1值為12,k2為22,執(zhí)行EXEC,發(fā)回nil,說(shuō)明事務(wù)回滾;查看下k1、k2的值都沒(méi)有被事務(wù)中的命令所改變。

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> WATCH k1
OK
127.0.0.1:6379> set k1 11
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 12
QUEUED
127.0.0.1:6379> set k2 22
QUEUED
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> get k1
"11"
127.0.0.1:6379> get k2
"v2"
  • UNWATCH取消監(jiān)視
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> WATCH k1
OK
127.0.0.1:6379> set k1 11
OK
127.0.0.1:6379> UNWATCH
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 12
QUEUED
127.0.0.1:6379> set k2 22
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
127.0.0.1:6379> get k1
"12"
127.0.0.1:6379> get k2
"22"
127.0.0.1:6379>

4 Redis事務(wù)執(zhí)行步驟??

通過(guò)上文命令執(zhí)行,很顯然Redis事務(wù)執(zhí)行是三個(gè)階段:

  • 開(kāi)啟:以MULTI開(kāi)始一個(gè)事務(wù)
  • 入隊(duì):將多個(gè)命令入隊(duì)到事務(wù)中,接到這些命令并不會(huì)立即執(zhí)行,而是放到等待執(zhí)行的事務(wù)隊(duì)列里面
  • 執(zhí)行:由EXEC命令觸發(fā)事務(wù)

當(dāng)一個(gè)客戶端切換到事務(wù)狀態(tài)之后, 服務(wù)器會(huì)根據(jù)這個(gè)客戶端發(fā)來(lái)的不同命令執(zhí)行不同的操作:

  • 如果客戶端發(fā)送的命令為 EXEC 、 DISCARD 、 WATCH 、 MULTI 四個(gè)命令的其中一個(gè), 那么服務(wù)器立即執(zhí)行這個(gè)命令。
  • 與此相反, 如果客戶端發(fā)送的命令是 EXEC 、 DISCARD 、 WATCH 、 MULTI 四個(gè)命令以外的其他命令, 那么服務(wù)器并不立即執(zhí)行這個(gè)命令, 而是將這個(gè)命令放入一個(gè)事務(wù)隊(duì)列里面, 然后向客戶端返回 QUEUED 回復(fù)。

更深入的理解

我們?cè)偻ㄟ^(guò)幾個(gè)問(wèn)題來(lái)深入理解Redis事務(wù)。

為什么 Redis 不支持回滾?

如果你有使用關(guān)系式數(shù)據(jù)庫(kù)的經(jīng)驗(yàn),那么“Redis 在事務(wù)失敗時(shí)不進(jìn)行回滾,而是繼續(xù)執(zhí)行余下的命令”這種做法可能會(huì)讓你覺(jué)得有點(diǎn)奇怪。

以下是這種做法的優(yōu)點(diǎn):

  • Redis 命令只會(huì)因?yàn)殄e(cuò)誤的語(yǔ)法而失敗(并且這些問(wèn)題不能在入隊(duì)時(shí)發(fā)現(xiàn)),或是命令用在了錯(cuò)誤類型的鍵上面:這也就是說(shuō),從實(shí)用性的角度來(lái)說(shuō),失敗的命令是由編程錯(cuò)誤造成的,而這些錯(cuò)誤應(yīng)該在開(kāi)發(fā)的過(guò)程中被發(fā)現(xiàn),而不應(yīng)該出現(xiàn)在生產(chǎn)環(huán)境中。
  • 因?yàn)椴恍枰獙?duì)回滾進(jìn)行支持,所以 Redis 的內(nèi)部可以保持簡(jiǎn)單且快速。

有種觀點(diǎn)認(rèn)為 Redis 處理事務(wù)的做法會(huì)產(chǎn)生 bug , 然而需要注意的是, 在通常情況下, 回滾并不能解決編程錯(cuò)誤帶來(lái)的問(wèn)題。舉個(gè)例子, 如果你本來(lái)想通過(guò) INCR 命令將鍵的值加上 1 , 卻不小心加上了 2 , 又或者對(duì)錯(cuò)誤類型的鍵執(zhí)行了 INCR , 回滾是沒(méi)有辦法處理這些情況的。

如何理解Redis與事務(wù)的ACID?

一般來(lái)說(shuō),事務(wù)有四個(gè)性質(zhì)稱為ACID,分別是原子性,一致性,隔離性和持久性

  • 原子性atomicity

    # 首先通過(guò)上文知道 運(yùn)行期的錯(cuò)誤是不會(huì)回滾的,很多文章由此說(shuō)Redis事務(wù)違背原子性的;而官方文檔認(rèn)為是遵從原子性的。Redis官方文檔給的理解是,**Redis的事務(wù)是原子性的:所有的命令,要么全部執(zhí)行,要么全部不執(zhí)行**。而不是完全成功
    
  • 一致性consistency

    #  redis事務(wù)可以保證命令失敗的情況下得以回滾,數(shù)據(jù)能恢復(fù)到?jīng)]有執(zhí)行之前的樣子,是保證一致性的,除非redis進(jìn)程意外終結(jié)
    
  • 隔離性Isolation

    #  redis事務(wù)是嚴(yán)格遵守隔離性的,原因是redis是單進(jìn)程單線程模式(v6.0之前),可以保證命令執(zhí)行過(guò)程中不會(huì)被其他客戶端命令打斷.但是,Redis不像其它結(jié)構(gòu)化數(shù)據(jù)庫(kù)有隔離級(jí)別這種設(shè)計(jì)
    
  • 持久性Durability

    #  **redis事務(wù)是不保證持久性的**,這是因?yàn)閞edis持久化策略中不管是RDB還是AOF都是異步執(zhí)行的,不保證持久性是出于對(duì)性能的考慮
    

5 Redis事務(wù)其它實(shí)現(xiàn)??

  • 基于Lua腳本,Redis可以保證腳本內(nèi)的命令一次性、按順序地執(zhí)行,其同時(shí)也不提供事務(wù)運(yùn)行錯(cuò)誤的回滾,執(zhí)行過(guò)程中如果部分命令運(yùn)行錯(cuò)誤,剩下的命令還是會(huì)繼續(xù)運(yùn)行完
  • 基于中間標(biāo)記變量,通過(guò)另外的標(biāo)記變量來(lái)標(biāo)識(shí)事務(wù)是否執(zhí)行完成,讀取數(shù)據(jù)時(shí)先讀取該標(biāo)記變量判斷是否事務(wù)執(zhí)行完成。但這樣會(huì)需要額外寫(xiě)代碼實(shí)現(xiàn),比較繁瑣

到此這篇關(guān)于Redis事務(wù)處理的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Redis事務(wù)處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis設(shè)置key的過(guò)期時(shí)間

    Redis設(shè)置key的過(guò)期時(shí)間

    本文主要介紹了Redis設(shè)置key的過(guò)期時(shí)間,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • 解讀redis?slaveof命令執(zhí)行后為什么需要清庫(kù)重新同步

    解讀redis?slaveof命令執(zhí)行后為什么需要清庫(kù)重新同步

    這篇文章主要介紹了redis?slaveof命令執(zhí)行后為什么需要清庫(kù)重新同步,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • redis發(fā)布訂閱模式的實(shí)現(xiàn)

    redis發(fā)布訂閱模式的實(shí)現(xiàn)

    本文主要介紹了redis發(fā)布訂閱模式,Redis?的?SUBSCRIBE?命令可以讓客戶端訂閱任意數(shù)量的頻道,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • 深度解析Redis?數(shù)據(jù)淘汰策略

    深度解析Redis?數(shù)據(jù)淘汰策略

    本文將深入剖析8種淘汰策略的機(jī)制,并結(jié)合Java代碼演示生產(chǎn)環(huán)境的最佳實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • Redis 大key的幾種刪除方式

    Redis 大key的幾種刪除方式

    大key刪除直接調(diào)用 del 命令刪除key,容易造成請(qǐng)求被阻塞,本文主要介紹了Redis 大key的幾種刪除方式,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • 基于Redis實(shí)現(xiàn)基本搶紅包算法詳解

    基于Redis實(shí)現(xiàn)基本搶紅包算法詳解

    [key, value]的緩存數(shù)據(jù)庫(kù), Redis官方性能描述非常高, 所以面對(duì)高并發(fā)場(chǎng)景, 使用Redis來(lái)克服高并發(fā)壓力是一個(gè)不錯(cuò)的手段, 本文主要基于Redis來(lái)實(shí)現(xiàn)基本的搶紅包系統(tǒng)設(shè)計(jì),感興趣的朋友跟隨小編一起看看吧
    2024-04-04
  • redis?消息隊(duì)列完成秒殺過(guò)期訂單處理方法(一)

    redis?消息隊(duì)列完成秒殺過(guò)期訂單處理方法(一)

    這篇文章主要介紹了redis?消息隊(duì)列完成秒殺過(guò)期訂單處理方法,包括redis?消息通知處理代金券過(guò)期問(wèn)題–失效問(wèn)題的分析,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • Redis大Key(Bigkey)問(wèn)題識(shí)別與解決全解析

    Redis大Key(Bigkey)問(wèn)題識(shí)別與解決全解析

    在高并發(fā)場(chǎng)景下,Redis 以極致的內(nèi)存操作速度成為緩存與NoSQL領(lǐng)域的首選,但隨著業(yè)務(wù)發(fā)展,大Key(Bigkey) 問(wèn)題逐漸顯現(xiàn),帶來(lái)內(nèi)存風(fēng)險(xiǎn)、性能瓶頸、集群失衡等隱患,本文給大家介紹了Redis大Key(Bigkey)問(wèn)題識(shí)別與解決,需要的朋友可以參考下
    2025-08-08
  • 深入理解Redis線程模型的原理及使用

    深入理解Redis線程模型的原理及使用

    Redis的線程模型整體還是多線程的,只是后臺(tái)執(zhí)行指令的核心線程是單線程的,整個(gè)線程模型可以理解為還是以單線程為主,基于這種單線程為主的線程模型,不同客戶端的各種指令都需要依次排隊(duì)執(zhí)行,下面就來(lái)詳細(xì)的了解一下
    2025-11-11
  • Redis Key命名規(guī)范實(shí)戰(zhàn)指南

    Redis Key命名規(guī)范實(shí)戰(zhàn)指南

    本文主要介紹了Redis Key命名規(guī)范實(shí)戰(zhàn)指南,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03

最新評(píng)論

无为县| 千阳县| 张家口市| 汪清县| 湘阴县| 如皋市| 象山县| 平遥县| 清水河县| 德清县| 长兴县| 中江县| 安阳县| 信阳市| 云南省| 大关县| 遵化市| 康乐县| 马关县| 肥东县| 昆明市| 梅州市| 安远县| 顺义区| 林口县| 五台县| 淮滨县| 屯门区| 钦州市| 砀山县| 客服| 巩留县| 兰坪| 连平县| 铜山县| 贵阳市| 托克逊县| 宁化县| 天等县| 昭通市| 金华市|