1. 程式人生 > >Redis(3)---Redis事務

Redis(3)---Redis事務

重新 返回 lsp 是什麽 行為 添加 很遺憾 app 持久

Redis事務

Redis 通過 MULTIEXECDISCARDWATCH 四個命令來實現事務功能。

MULTI :標記一個事務塊的開始。

EXEC: 執行所有事務塊內的命令。

DISCARD :取消事務,放棄執行事務塊內的所有命令。

WATCH key [key ...] :監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麽事務將被打斷。

一、事務

1、是什麽?

可以一次執行多個命令,本質是一組命令的集合。一個事務中的所有命令都會序列化,不許加塞!

2、能幹什麽?

一個隊列中,一次性的、順序性的、排他性的執行一系列的命令。要麽一起成功,要麽一起失敗。排好隊,一次性的執行多個redis的命令!

3、怎麽玩?

通過MULTI指令開啟,之後輸入多個命令!Redis將它們加入到隊列當中,所有的命令通過EXEC來開啟執行!通過DISCARD來放棄本次的批處理操作!

(1)正常執行(好比購物先加入購物車,最後EXEC統一結賬。)

192.168.1.66:6379> MULTI    --開啟事務
OK
192.168.1.66:6379> set k1 v1
QUEUED
192.168.1.66:6379
> set k2 v2 QUEUED 192.168.1.66:6379> set k3 v3 QUEUED 192.168.1.66:6379> set k4 v4 QUEUED 192.168.1.66:6379> get k2 QUEUED 192.168.1.66:6379> EXEC --結束事務 1) OK 2) OK 3) OK 4) OK 5) "v2"

(2)DISCARD 撤銷所有操作!

192.168.1.66:6379> MULTI
OK
192.168.1.66:6379> set
k1 11 QUEUED 192.168.1.66:6379> set k2 22 QUEUED 192.168.1.66:6379> set k3 33 QUEUED 192.168.1.66:6379> DISCARD OK 192.168.1.66:6379> get k1 --這裏的k1的value值還是上面的值,而不是新設置的value值 "v1"

(3)加入隊列時不出錯,下面的都將正常運行,執行時出錯不影響其他語句!

192.168.1.66:6379> set k1 v1
OK
192.168.1.66:6379> set k2 v2
OK
192.168.1.66:6379> MULTI
OK
192.168.1.66:6379> incr k1
QUEUED
192.168.1.66:6379> set k2 22
QUEUED
192.168.1.66:6379> EXEC
1) (error) ERR value is not an integer or out of range --在運行是才發現k1不是數字,報錯
2) OK     --執行成功

註意:
(1)當遇到執行錯誤時,redis放過這種錯誤,保證事務執行完成。(所以說redis的事務並不是保證原子性
(2)與mysql中事務不同,在redis事務遇到執行錯誤的時候,不會進行回滾,而是簡單的放過了,並保證其他的命令正常執行。這個區別在實現業務的時候,需要自己保證邏輯符合預期。
(3)當事務的執行過程中,如果redis意外的掛了。很遺憾只有部分命令執行了,後面的也就被丟棄了。當然如果我們使用的append-only file方式持久化,redis會用單個write操作寫入整個事務內容。即是是這種方式還是有可能只部分寫入了事務到磁盤。發生部分寫入事務的情況 下,redis重啟時會檢測到這種情況,然後失敗退出。可以使用redis-check-aof工具進行修復,修復會刪除部分寫入的事務內容。修復完後就 能夠重新啟動了。

二、WATCH

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

WATCH 的鍵會被監視,並會發覺這些鍵是否被改動過了。 如果有至少一個被監視的鍵在 EXEC 執行之前被修改了, 那麽整個事務都會被取消, EXEC 返回空多條批量回復(null multi-bulk reply)來表示事務已經失敗。

1、首先我們不加WATCH進行事務處理

時間

客戶端 A

客戶端 B

說明

T1

SET name aa

SET age 10

GET name

aa

GET age

10

數據庫中兩客戶端登錄,及鍵初始值。

它們是同步的。

T2

MULTI

SET name bb

Incr age

此時,客戶端1開啟事務,並提交隊列命令:

1.想要將當前age自增+1運算;

2.將name值改為bb

T3

SET name cc

Incr age

此時,客戶端2修改了age值

同時修改name值為cc

T4

EXEC

T5

GET name

bb

GET age

12

此時,客戶端1執行隊列命令,發現運算之後age不是理想中的11,而是12原因是被其它客戶插足搶先給修改了。name值確實是沒有被其它所改變。這樣可能導致數據不一致性。

2、添加WARCH

客戶端1-引入“樂觀鎖”機制 客戶端2 說明
SET age
"10"
SET name
"zhangsan"

GET age
"10"
GET name
"zhangsan"
數據庫中兩客戶端登錄,及鍵初始值。
WATCH age name
OK
MUTLI
OK
incr age
QUEUED
set name lisi
QUEUED
  此時,客戶端1用watch命令監視age和name,然後開啟事務,並提交隊列命令
  incr age
(integer) 11
此時,客戶端2修改了age值

exec
(nil)
get age
"11"
get name
"zhangsan"
  此時,客戶端1執行隊列命令,由watch監控發現此期間age的值已經被修改過,則讓事整個務回滾,不做任何動作。

watch可以同時監控多個鍵,在監控期間只要有一個鍵被其它客戶端改變,則整個事務回滾。

想太多,做太少,中間的落差就是煩惱。想沒有煩惱,要麽別想,要麽多做。少校【1】

Redis(3)---Redis事務