日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Redis事务介绍

發布時間:2023/11/27 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis事务介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

相信學過Mysql等其他數據庫的同學對事務這個詞都不陌生,事務表示的是一組動作,這組動作要么全部執行,要么全部不執行。為什么會有這樣的需求呢?看看下面的場景:

  • 微博是一個弱關系型社交網絡,用戶之間有關注和被關注兩種關系,比如兩個用戶A和B,如果A關注B,則B的粉絲中就應該有A。關注這個動作需要兩個步驟完成:在A的關注者中添加B;在B的粉絲中添加A。 這兩個動作要么都執行成功,要么都不執行。否則就可能會出現A關注了B,但是B的粉絲中沒有A的不可容忍的情況。
  • 轉賬匯款,假設現在有兩個賬戶A和B,現在需要將A中的一萬塊大洋轉到B的賬戶中,這個動作也需要兩個步驟完成:從A的賬戶中劃走一萬塊;在B的賬戶中增加一萬塊。這兩個動作要么全部執行成功,要么全部不執行,否則自會有人問候你的!!!

Redis作為一種高效的分布式數據庫,同樣支持事務。

Redis事務

Redis中的事務(transaction)是一組命令的集合。事務同命令一樣都是Redis最小的執行單位,一個事務中的命令要么都執行,要么都不執行。Redis事務的實現需要用到?MULTI??EXEC?兩個命令,事務開始的時候先向Redis服務器發送?MULTI?命令,然后依次發送需要在本次事務中處理的命令,最后再發送?EXEC?命令表示事務命令結束。

舉個例子,使用redis-cli連接redis,然后在命令行工具中輸入如下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set url http://qifuguang.me
QUEUED
127.0.0.1:6379> set title winwill2012
QUEUED
127.0.0.1:6379> set desc java
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) OK
127.0.0.1:6379>
127.0.0.1:6379> get url
"http://qifuguang.me"
127.0.0.1:6379> get title
"winwill2012"
127.0.0.1:6379> get desc
"java"
127.0.0.1:6379>

從輸出中可以看到,當輸入MULTI命令后,服務器返回OK表示事務開始成功,然后依次輸入需要在本次事務中執行的所有命令,每次輸入一個命令服務器并不會馬上執行,而是返回”QUEUED”,這表示命令已經被服務器接受并且暫時保存起來,最后輸入EXEC命令后,本次事務中的所有命令才會被依次執行,可以看到最后服務器一次性返回了三個OK,這里返回的結果與發送的命令是按順序一一對應的,這說明這次事務中的命令全都執行成功了。

再舉個例子,在命令行工具中輸入如下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a a
QUEUED
127.0.0.1:6379> sett b b
(error) ERR unknown command 'sett'
127.0.0.1:6379> set c c
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get a
(nil)
127.0.0.1:6379> get b
(nil)
127.0.0.1:6379> get c
(nil)
127.0.0.1:6379>

和前面的例子一樣,先輸入MULTI最后輸入EXEC表示中間的命令屬于一個事務,不同的是中間輸入的命令有一個錯誤(set寫成了sett),這樣因為有一個錯誤的命令導致事務中的其他命令都不執行了(通過后續的get命令可以驗證),可見事務中的所有命令式同呼吸共命運的。

如果客戶端在發送EXEC命令之前斷線了,則服務器會清空事務隊列,事務中的所有命令都不會被執行。而一旦客戶端發送了EXEC命令之后,事務中的所有命令都會被執行,即使此后客戶端斷線也沒關系,因為服務器已經保存了事務中的所有命令。

除了保證事務中的所有命令要么全執行要么全不執行外,Redis的事務還能保證一個事務中的命令依次執行而不會被其他命令插入。試想一個客戶端A需要執行幾條命令,同時客戶端B發送了幾條命令,如果不使用事務,則客戶端B的命令有可能會插入到客戶端A的幾條命令中,如果想避免這種情況發生,也可以使用事務。

Redis事務錯誤處理

如果一個事務中的某個命令執行出錯,Redis會怎樣處理呢?要回答這個問題,首先要搞清楚是什么原因導致命令執行出錯:

  1. 語法錯誤?就像上面的例子一樣,語法錯誤表示命令不存在或者參數錯誤
    這種情況需要區分Redis的版本,Redis 2.6.5之前的版本會忽略錯誤的命令,執行其他正確的命令,2.6.5之后的版本會忽略這個事務中的所有命令,都不執行,就比如上面的例子(使用的Redis版本是2.8的)

  2. 運行錯誤?運行錯誤表示命令在執行過程中出現錯誤,比如用GET命令獲取一個散列表類型的鍵值。
    這種錯誤在命令執行之前Redis是無法發現的,所以在事務里這樣的命令會被Redis接受并執行。如果食物里有一條命令執行錯誤,其他命令依舊會執行(包括出錯之后的命令)。比如下例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set key 1
    QUEUED
    127.0.0.1:6379> SADD key 2
    QUEUED
    127.0.0.1:6379> set key 3
    QUEUED
    127.0.0.1:6379> EXEC
    1) OK
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
    3) OK
    127.0.0.1:6379> get key
    "3"

    Redis中的事務并沒有關系型數據庫中的事務回滾(rollback)功能,因此使用者必須自己收拾剩下的爛攤子。不過由于Redis不支持事務回滾功能,這也使得Redis的事務簡潔快速。

回顧上面兩種類型的錯誤,語法錯誤完全可以在開發的時候發現并作出處理,另外如果能很好地規劃Redis數據的鍵的使用,也是不會出現命令和鍵不匹配的問題的。

WATCH命令

從上面的例子我們可以看到,事務中的命令要全部執行完之后才能獲取每個命令的結果,但是如果一個事務中的命令B依賴于他上一個命令A的結果的話該怎么辦呢?就比如說實現類似Java中的i++的功能,先要獲取當前值,才能在當前值的基礎上做加一操作。這種場合僅僅使用上面介紹的MULTI和EXEC是不能實現的,因為MULTI和EXEC中的命令是一起執行的,并不能將其中一條命令的執行結果作為另一條命令的執行參數,所以這個時候就需要引進Redis事務家族中的另一成員:WATCH命令

換個角度思考上面說到的實現i++的方法,可以這樣實現:

  1. 監控i的值,保證i的值不被修改
  2. 獲取i的原值
  3. 如果過程中i的值沒有被修改,則將當前的i值+1,否則不執行

這樣就能夠避免競態條件,保證i++能夠正確執行。

WATCH命令可以監控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之后的事務就不會執行,監控一直持續到EXEC命令(事務中的命令是在EXEC之后才執行的,EXEC命令執行完之后被監控的鍵會自動被UNWATCH)

舉個例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
127.0.0.1:6379> set mykey 1
OK
127.0.0.1:6379> WATCH mykey
OK
127.0.0.1:6379> set mykey 2
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set mykey 3
QUEUED
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> get mykey
"2"
127.0.0.1:6379>

上面的例子中,首先設置mykey的鍵值為1,然后使用WATCH命令監控mykey,隨后更改mykey的值為2,然后進入事務,事務中設置mykey的值為3,然后執行EXEC運行事務中的命令,最后使用get命令查看mykey的值,發現mykey的值還是2,也就是說事務中的命令根本沒有執行(因為WATCH監控mykey的過程中,mykey被修改了,所以隨后的事務便會被取消)。

有了WATCH命令,我們就可以自己實現i++功能了,偽代碼如下:

1
2
3
4
5
6
7
8
9
10
11
def incr($key):
WATCH $key
$value = GET $key
if not $value
$value = 0
$value = $value + 1

MULTI
SET $key $value
result = EXEC
return result[0]

因為EXEC返回的是多行字符串,使用result[0]表示返回值的第一個字符串。

注意:由于WATCH命令的作用只是當被監控的鍵被修改后取消之后的事務,并不能保證其他客戶端不修改監控的值,所以當EXEC命令執行失敗之后需要手動重新執行整個事務。

執行EXEC命令之后會取消監控使用WATCH命令監控的鍵,如果不想執行事務中的命令,也可以使用UNWATCH命令來取消監控。

聲明

原創文章,轉載請注明出處,本文鏈接:http://qifuguang.me/2015/09/30/Redis事務介紹/
如果你喜歡我的文章,請關注我的微信訂閱號,更多干貨,第一時間與你分享:

轉載于:https://www.cnblogs.com/thrillerz/p/5036327.html

總結

以上是生活随笔為你收集整理的Redis事务介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。