1. 程式人生 > >Redis事務

Redis事務

errors 隊列 存儲介質 val car 回滾 company 開發 中斷

Redis事務

Redis通過 MULTI EXEC WATCH 等命令來實現事務功能。事務提供了一種將多個命令請求打包,然後一次性、按順序地執行多個命令的機制,並且在事務執行期間,服務器不會中斷事務而改去執行其他客戶端的命令請求,它會將事務中的所有命令都執行完畢,然後才去處理其他客戶端的命令請求。

1.事務的實現

下面給了一個事務的簡單例子:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set "name" "wangjia06"
QUEUED
127.0.0.1:6379> get "name"
QUEUED
127.0.0.1:6379> set "company" "dianping"
QUEUED
127.0.0.1:6379> get "company"
QUEUED
127.0.0.1:6379> set age 28
QUEUED
127.0.0.1:6379> get age
QUEUED
127.0.0.1:6379> exec
1) OK
2) "wangjia06"
3) OK
4) "dianping"
5) OK
6) "28"

退出一個事務可以用 MULTI 命令, 此時再執行事務會報錯:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> get "company"
QUEUED
127.0.0.1:6379> get "age"
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI

一個事務包括三個步驟:

  • 事務開始:事務以 MULTI 開始,返回OK命令。
  • 命令入隊:每個事務命令成功進入隊列後,返回 QUEUED
  • 事務執行: EXEC 執行事務。

Redis事務內會遇到兩種錯誤:

  • 隊列入隊不成功:語法錯誤,錯誤的命令名字或者一些重要的條件如OOM條件。這種客戶端會進行校驗,如果入隊成功則返回QUEUED ,否則返回錯誤。如果一個命令入隊失敗,大多數客戶端會終止該事務。
127.0.0.1:6379> get name
"wangjia08"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name "wangjia09"
QUEUED
127.0.0.1:6379> get
(error) ERR wrong number of arguments for ‘get‘ command
127.0.0.1:6379> get name
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379>
  • 命令執行時報錯:如對一個String值進行列表操作。所有其他的命令會被正常執行即使在事務執行中一些命令失敗。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set sex man
QUEUED
127.0.0.1:6379> lpop sex
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> get sex
"man"
127.0.0.1:6379>

Redis不支持事務回滾功能,原因大概有兩點:

  • 一個redis命令執行失敗,一般是語法錯誤或者應該在開發階段被檢測出來,而不是在生產環境。
  • redis追求簡單、速度快,所以不提供事務回滾功能.

2.WATCH命令的實現

watch 命令給redis事務提供了一個 CAS 功能。它是一個樂觀鎖,檢查被監視的健是否至少有一個已經被修改過了,如果是的話拒絕執行,並返回nil代表執行失敗。

如下面例子,在一個客戶端開啟事務前對鍵“name”進行監視,若在這個事務執行前,另一個客戶端修改了鍵“name”的值,之後事務執行後就會報nil。

127.0.0.1:6379> watch "name"
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set age 10
QUEUED
127.0.0.1:6379> get "name"
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> set "name" "wangjia08"
OK

watch 命令監視多個鍵:

127.0.0.1:6379> watch "name" "age"
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> get "name"
QUEUED
127.0.0.1:6379> get "age"
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379>
127.0.0.1:6379> set "age" 11
OK

3.事務的ACID性質

  • 原子性:redis事務多個操作當做一個整體來執行,要麽執行事務中的所有操作,要麽一個也不執行。
  • 一致性:“一致”指的是數據符合數據庫本身的定義和要求,沒有包含非法的或無效的錯誤數據
    • 入隊錯誤:服務器拒絕執行該事務。
    • 執行錯誤:出錯的命令會被服務器識別出來,並進行相應的錯誤處理,不會對數據庫做任何修改,也不會對數據一致性造成影響。
    • 服務器停機: RDB AOF 還原數據庫狀態
  • 隔離性:單線程執行事務,且服務器保證事務期間不會對事務進行中斷
  • 持久性:當一個事務執行完畢時,執行這個事務所得的結果已經被保存到永久性存儲介質(比如硬盤)裏面了。Redis事務的持久性由Redis所使用的持久化模式決定(無持久化模式、 RDB AOF )。Redis工作在無持久化模式下時,事務無持久性。在 AOF 模式下 appenfsync no 時,事務也無持久性

Redis事務