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

歡迎訪問 生活随笔!

生活随笔

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

生活经验

Redis 笔记(08)— 事务(一次执行多条命令、命令 watch/multi/exec/discard、错误处理)

發布時間:2023/11/28 生活经验 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis 笔记(08)— 事务(一次执行多条命令、命令 watch/multi/exec/discard、错误处理) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 事務概念

Redis 中的事務 (transaction)是一組命令的集合。事務同命令一樣是 Redis 的最小執行單位,一個事務中的命令要么都執行,要么都不執行。事務的原理是先將屬于一個事務的命令發送給 Redis,然后再讓 Redis 依次執行這些命令。

2. 事務命令

命令說明
watch key[key…]鎖定key,直到執行了multi/exec命令
multi標記一個事務塊開始
exec執行所有multi之后發的命令
discard丟棄所有multi之后發的命令

3. 事務使用

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> set c 3
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) OK
127.0.0.1:6379> 

multi 標記一個事務的開始,表示之后發送的命令都屬于同一個事務,而 exec 命令則告訴 Redis 將等待執行的事務隊列中的所有命令(即剛才返回 QUEUED 的命令)按照發送順序依次執行。exec 命令的返回值是事務命令的返回值組成的列表,返回值順序和命令的順序相同。

Redis 會保證一個事務中的命令要么都執行,要么都不執行。 如果在執行 exec 命令之前客戶端斷線了那么 Redis 會自動清空事務隊列,事務中的所有命令都不會執行;而如果客戶端執行了 exec 命令后斷線也沒有關系,Redis 已經記錄了所有要執行的命令。

所有的指令在 exec 之前不執行,而是緩存在服務器的一個事務隊列中,服務器一旦收到 exec 指令,才開執行整個事務隊列,執行完畢后一次性返回所有指令的運行結果。因為 Redis 的單線程特性,它不用擔心自己在執行隊列的時候被其它指令打攪,可以保證他們能得到的「原子性」執行。

Redis 為事務提供了一個 discard 指令,用于丟棄事務緩存隊列中的所有指令,在 exec 執行之前。

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set x 1
QUEUED
127.0.0.1:6379(TX)> set y 2
QUEUED
127.0.0.1:6379(TX)> set z 3
QUEUED
127.0.0.1:6379(TX)> discard		# 丟棄 multi 之后發送的命令
OK
127.0.0.1:6379> get x
(nil)
127.0.0.1:6379> mget x y z
1) (nil)
2) (nil)
3) (nil)
127.0.0.1:6379> 

4. 錯誤處理

如果 Redis 事務中一個命令發生錯誤,那么其它的命令還會執行嗎?我們主要看兩種錯誤:

  • 語法錯誤

    只要事務中有一個命令的語法發生錯誤,那么整個事務中的命令都不會執行。

  • 運行錯誤

    運行錯誤是指在執行命令時出現的錯誤,這種錯誤在實際執行之前是無法發現的,當事務中出現這種運行錯誤時,其它命令仍然會繼續執行的。

> multi
OK
> set books python
QUEUED
> incr books
QUEUED
> set phone huawei
QUEUED
> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
> get books
"python"
> get phone 
"huawei"

上面的例子是事務執行到中間遇到失敗了,因為我們不能對一個字符串進行數學運算,事務在遇到指令執行失敗后,后面的指令還繼續執行,所以 phone 的值能繼續得到設置。

到這里,你應該明白 Redis 的事務根本不能算「原子性」,而僅僅是滿足了事務的「隔離性」,隔離性中的串行化——當前執行的事務有著不被其它事務打斷的權利。

Redis 事務不支持關系型數據庫事務提供的回滾功能。

5. watch 命令

watch 命令可以監控一個或者多個鍵,一旦其中有一個鍵被修改或刪除,之后的事務就不會執行。監控一直持續到 exec 命令 (事務中的命令是在 exec 命令之后執行的,所以在 multi 命令之后可以修改 watch 監控的鍵值)。

watch 會在事務開始之前盯住 1 個或多個關鍵變量,當事務執行時,也就是服務器收到了 exec 指令要順序執行緩存的事務隊列時,Redis 會檢查關鍵變量自 watch 之后,是否被修改了 (包括當前事務所在的客戶端)。如果關鍵變量被人動過了,exec 指令就會返回 null 回復告知客戶端事務執行失敗,這個時候客戶端一般會選擇重試。

127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> watch a		# 監控 a 是否變化
OK
127.0.0.1:6379> set a 2		# 鍵被修改,則后面的 multi 不會被執行
OK
127.0.0.1:6379> multi 
OK
127.0.0.1:6379> set a 3
QUEUED
127.0.0.1:6379> exec		# 變量被修改,服務器回復 nil
(nil)
127.0.0.1:6379> get a		# 被修改之后的值,multi 命令之后的值沒有被執行
"2"
127.0.0.1:6379> 

也可以用 unwatch 命令來取消監控。

Redis事務在執行時是單線程運行的。但是在執行前有可能別的客戶端已經修改了事務里執行的 key 。所以在 multi 事務開始之前用 watch 檢測這個 key 避免被其他客戶端改變的。如果這個 key 被改變 了 exec 的時候就會報錯不執行這個事務。

Redis 禁止在 multiexec 之間執行 watch 指令,而必須在 multi 之前做好盯住關鍵變量,否則會出錯。

6. 事務結合管道使用

Redis 事務在發送每個指令到事務緩存隊列時都要經過一次網絡讀寫,當一個事務內部的指令較多時,需要的網絡 IO 時間也會線性增長。所以通常 Redis 的客戶端在執行事務時都會結合 pipeline 一起使用,這樣可以將多次 IO 操作壓縮為單次 IO 操作。

比如我們在使用 PythonRedis 客戶端時執行事務時是要強制使用 pipeline 的。

pipe = redis.pipeline(transaction=true)
pipe.multi()
pipe.incr("books")
pipe.incr("books")
values = pipe.execute()

總結

以上是生活随笔為你收集整理的Redis 笔记(08)— 事务(一次执行多条命令、命令 watch/multi/exec/discard、错误处理)的全部內容,希望文章能夠幫你解決所遇到的問題。

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