Redis事務和樂觀鎖

2021-09-02 10:39:42 字數 1924 閱讀 9230

一.事務定義

二.rdis事務

1) mutli開啟事務

multi 執行之後, 客戶端可以繼續向伺服器傳送任意多條命令, 這些命令不會立即被執行, 而是被放到乙個佇列中, 當 exec 命令被呼叫時, 所有佇列中的命令才會被執行

2) exec:提交事務

如果客戶端在使用 multi 開啟了乙個事務之後,卻因為斷線而沒有成功執行 exec ,那麼事務中的所有命令都不會被執行。

另一方面,如果客戶端成功在開啟事務之後執行 exec ,那麼事務中的所有命令都會被執行。

3) discard取消事務

記住,此指令不是嚴格意義上的「事務回滾」,只是表達了「事務操作被取消」的語義,客戶端會清空事務的操作佇列, 並放棄執行事務

**例項
> multi

ok> incr foo

queued

> incr bar

queued

> exec

1) (integer) 1

2) (integer) 1

4) 擴充套件

當使用 aof 方式做持久化的時候, redis 會使用單個 write(2) 命令將事務寫入到磁碟中。

然而,如果 redis 伺服器因為某些原因被管理員殺死,或者遇上某種硬體故障,那麼可能只有部分事務命令會被成功寫入到磁碟中。

如果 redis 在重新啟動時發現 aof 檔案出了這樣的問題,那麼它會退出,並匯報乙個錯誤。

使用 redis-check-aof 程式可以修復這一問題:它會移除 aof 檔案中不完整事務的資訊,確保伺服器可以順利啟動。

二.redis watch 實現樂觀鎖

watch/unwatch:「監控」,這個操作也可以說是redis的特殊功能,在事務開啟「mutil」前,可以對某個key註冊「watch」,如果在事務提交後,將會首先檢測「watch」列表中的key集合是否被其他客戶端修改,如果任意乙個key 被修改,都將會導致事務直接被「discard清空事務操作佇列;事務執行成功或者被discard,都將會導致watch key被「unwatch」,因此事務之後,你需要重新watch。watch需要在事務開啟之前執行。

舉個例子, 假設我們需要原子性地為某個值進行增 1 操作(假設 incr 不存在)。

val = get mykey

val = val + 1

set mykey $val

上面的這個實現在只有乙個客戶端的時候可以執行得很好。 但是, 當多個客戶端同時對同乙個鍵進行這樣的操作時, 就會產生競爭條件。

舉個例子, 如果客戶端 a 和 b 都讀取了鍵原來的值, 比如 10 , 那麼兩個客戶端都會將鍵的值設為 11 , 但正確的結果應該是 12 才對。

有了 watch , 我們就可以輕鬆地解決這類問題了:

watch mykey

val = get mykey

val = val + 1

multi

set mykey $val

exec

使用上面的**, 如果在 watch 執行之後, exec 執行之前, 有其他客戶端修改了 mykey 的值, 那麼當前客戶端的事務就會失敗。 程式需要做的, 就是不斷重試這個操作, 直到沒有發生碰撞為止。

這種形式的鎖被稱作樂觀鎖, 它是一種非常強大的鎖機制。 並且因為大多數情況下, 不同的客戶端會訪問不同的鍵, 碰撞的情況一般都很少, 所以通常並不需要進行重試。

Redis事務和樂觀鎖

redis對事務的支援目前還比較簡單.redis只能保證乙個client發起的事務中的命令可以連續的執行,而中間不會插入其他client的命令.由於redis是單執行緒來處理所有client的請求的所以做到這點是很容易的.一般情況下redis在接受到乙個client發來的命令後會立即處理並 返回處理...

Redis22 事務和樂觀鎖

redis使用multi開啟事務,exec來執行,discard來回滾 事務中的指令會快取在伺服器中的乙個事務佇列中,伺服器一旦受到exec指令就會順序的執行所有指令並返回所有的執行結果,這些指令在執行時不會相互影響,因為redis是單執行緒的。redis的事務並不是原子性的,一次事務的執行過程中如...

Redis鎖,悲觀鎖和樂觀鎖

樂觀鎖開啟事務前,設定對資料的監聽 watch exec時,如果發生資料發生過修改,作用於改資料的事務會自動取消 discard 事務exec後,無論成敗,監聽會被移除 悲觀鎖每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖。場景 如果專案中使用了快取且對快取設定了超時時間。當併發...