Redis事務(Redis事務與普通關係型數據庫事務的區別)

前言

Redis作爲非關係型數據庫中的一種,因爲其基於內存、單線程、支持持久化、擁有着高速的讀寫速度而又支持多種數據類型、支持原生集羣等特點而被廣泛使用。這篇博文主要討論下Redis事務與關係型數據庫(比如MySQL)事務之間的區別。

Redis事務

Redis事務與MySQL事務一樣,一次事務可以執行多條命令,在事務執行時命令按順序執行。由MULTI命令標誌着事務的開始,EXEC命令標誌着開始執行事務內的所有命令。MULTI和EXEC命令將一個事務的過程劃分爲兩個階段,MULTI命令開啓組隊階段,在組隊階段主要是將命令依次送入緩衝隊列中;EXEC命令開啓執行階段,從緩衝隊列中取出命令執行。

在組隊階段,其它客戶端的命令會影響該事務內命令所操作的key,可以通過WATCH命令來監聽一個或者多個key來判斷key值是否改變,一旦有一個key值改變則中斷事務放棄事務中的所有命令,再者,在組隊階段若發生錯誤,Redis會中斷事務放棄事務中的所有命令。
在這裏插入圖片描述
一旦執行EXEC命令,事務進入執行階段,則外界其它客戶端的命令無法插入其中,無法影響事務操作的結果。其它客戶端無法插入到事務的衆多命令中,則無法影響事務操作結果的原因在於Redis服務端處理請求是單線程,在處理這個事務的一段時間內,服務端無法並行的執行其它命令,自然也就無法影響事務操作結果(即使使用Redis集羣,Redis會根據事務命令操作的key值將命令請求分配到對應的服務器上,Redis服務端在不同的機器上也是單線程處理請求,在那一段時間內只能執行事務的命令)。再者事務在執行過程中若有命令執行失敗,則該命令不被執行而是跳過該命令,其它命令繼續執行,也就是說Redis事務在執行過程中不因某一個命令的失敗而產生事務回滾操作。例如一個事務包含A、B、C、D四條命令,執行過程中依次執行,執行完A、B,在執行C時發生錯誤,則跳過命令C,繼續執行D命令,事務結束後A、B、D命令成功執行,產生影響結果。
在這裏插入圖片描述

Redis命令

MULTI開啓組隊階段。
EXEC開啓執行階段。
DISCARD命令只能在組隊階段使用。
WATCH和UNWATCH命令也是在組隊階段使用,用以實現對key的監聽,防止key被其它命令所改動。這種機制其實就相當於樂觀鎖,由於數據存儲在內存中,無需進行耗時的I/O,其實事務很快就能執行完成,則Redis樂觀的認爲我無需加鎖,然後通過WATCH命令來進行檢測,若是數據不幸被改動了,我再來補償,將被改動的消息拋給用戶程序進行處理。
在這裏插入圖片描述

事務的應用場景

Redis命令根據其特點應用於一組命令需要同一批執行,且要保證一組命令在執行的過程之中不被其它命令插入。例如商品秒殺。

Redis事務與普通關係型數據庫事務的區別

一般提到事務,我們都能想到事務的四特性(ACID),這裏將從事務特性的角度來分析Redis事務與普通關係型數據庫事務的區別。

事務特性(ACID)

原子性(Atomicity): 事務的原子性是指事物是最小的執行單位,不允許分割,事務內的一系列操作,要不都執行,要不都不執行。

一致性(Consistency): 事物的提交只會導致數據庫的狀態從一個一致性狀態到另外一個一致性狀態,換句話來說就是事務一系列操作的中間操作導致的中間不一致狀態不會讓別的事務看到。一致性狀態指的是多個事務訪問到的數據庫的數據和數據結構是一致的。

隔離性(Isolation): 事務的隔離性是指併發事務在執行過程中不能相互影響,其對數據庫的影響和它們串行執行時一樣。

持久性(Durability): 一個事務被提交之後。它對數據庫中數據的改變是持久的,即使數據庫發生故障也不會導致提交改變結果的丟失。

事務特性區別分析

原子性分析: 首先來看下Redis是否具有原子性,首先Redis不支持事務回滾操作,Redis事務在組隊階段若某一個命令出錯會中斷事務放棄事務內的所有命令;但到了真正的執行階段,若事務內某一個命令執行出錯,卻不影響其它命令,拋棄出錯命令,其它命令照常執行,以此看來Redis並不滿足原子性的事務內命令要不都執行要不都不執行的特性,因此Redis事務並沒有原子性。從這個角度來看,Redis事務更像一個批量處理的操作。

隔離性分析: Redis是用單線程來處理請求,天然就具有隔離性,因爲它本來就是串行的執行命令,具有最高的隔離級別。其它客戶端的命令無法在Redis事務執行的過程中插入進去,自然也無法影響其事務執行。

持久性分析: Redis與Memcached的一個區別就是Redis支持持久化,Redis支持RDB(快照)和AOF兩種持久化機制(當然Redis也可以設置爲不進行持久化)。RDB的機制是每隔一段時間將內存中發生變化的數據以快照的方式存儲到磁盤dump.rdb文件中;而AOF是每當有寫命令執行時,都將寫命令寫入磁盤的appendonly.aof文件中(也可以設置爲每隔一秒將寫命令寫入文件),以便機器重啓時通過寫命令再將數據更新到內存中,AOF方式持久化的實時性更好。以此看來Redis事務其實是具有持久性的,若它使用的是AOF方式的每當有寫命令,都將命令寫入磁盤文件,可以保證事務的持久性。

一致性分析: Redis單線程處理請求以及Redis事務在執行時不允許別的命令插入的特點就決定了事務中間操作導致的中間一致性狀態不會被其它事務所看到,且Redis可在機器宕機後通過持久化的文件恢復到一致性狀態,從這些角度看,Redis事務貌似具有一致性。但Redis不支持事務回滾,意味着它很可能導致現實意義中的不一致性,例如常見的例子銀行轉賬,賬號A給B轉賬100,命令有兩條,分別是賬號A減去100和賬號B加上100,若第一條命令出錯,而第二條命令正常執行,就導致了不一致性。其實Redis爲了保持簡潔和效率,放棄了事務回滾,也就放棄了原子性和一致性,因爲事務回滾主要是在命令出錯時保持數據的一致性,而在Redis中,命令出錯主要是編程人員使用錯誤,而這點應該在開發中被發現,而不是在使用過程中,因此Redis認爲我不需要爲你的錯誤買單,Redis放棄了事務回滾的機制。因此Redis不具有傳統事務的一致性。

Redis常用來做緩存而不是真正意義上的數據庫,不是用來永久存儲數據,因此Redis的很多設計理念與普通關係型數據庫並不一致,Redis事務爲了簡潔和快速拋棄了事務回滾,也就同時拋棄了原子性和一致性,事務操作更像是一個批量操作了,只是在批量操作過程中不允許別的事務或者命令加塞,插入進來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章