Redis中的事務介紹
MySQL中的事務大家都不陌生,Redis中的事務和MySQL中的事務不同,今天看下Redis事務中的一些知識點吧。
01 事務簡介
Redis中的事務使用multi、exec來標記,其中multi代表事務開始,exec代表事務結束,multi和exec之間的命令是原子順序執行的。下面是一個例子:
- 127.0.0.1:7397> multi
- OK
- 127.0.0.1:7397> set key_hello hello
- QUEUED
- 127.0.0.1:7397> set key_world world
- QUEUED
- 127.0.0.1:7397> exec
- 1) OK
- 2) OK
需要注意的是,命令執行的中間結果返回都是queued,也就是說放到了隊列里面,沒有真正執行。在exec之前,如果使用get命令來查看當前的key_hello或者key_world的值,是無法獲取到的。
02 命令錯誤導致的事務提交失敗,所有命令都不執行
如果調用API的時候,拼寫錯誤,則會造成整個事務無法執行,例如下面的例子:
- 127.0.0.1:7397> multi
- OK
- 127.0.0.1:7397> incr counter
- QUEUED
- 127.0.0.1:7397> sett key_a aa
- (error) ERR unknown command `sett`, with args beginning with: `key_a`, `aa`,
- 127.0.0.1:7397> exec
- (error) EXECABORT Transaction discarded because of previous errors.
- 127.0.0.1:7397> get counter
- "10"
可以看到,因為set拼寫錯誤,寫成了sett,整個事務內部的所有動作都失效。exec命令也報錯。
03 運行時錯誤導致數據錯誤
如果語法正確,但是在運行的時候出現了"運行時"錯誤,例如元素的類型和操作符不匹配,例如對字符型值進行自增操作,如下:
- 127.0.0.1:7397> get key_a
- "a"
- 127.0.0.1:7397> get key_b
- "b"
- 127.0.0.1:7397> multi
- OK
- 127.0.0.1:7397> incr key_a
- QUEUED
- 127.0.0.1:7397> set key_b bbb
- QUEUED
- 127.0.0.1:7397> exec
- 1) (error) ERR value is not an integer or out of range
- 2) OK
- 127.0.0.1:7397> get key_b
- "bbb"
對key_a進行自增這類錯誤,它的語法是正確的,但是由于key_a是字符型的,自增操作是不合適的,事務中還對key_b進行了賦值操作,在執行exec的時候,key_b的值是被修改的,從"b"變成了“bbb”。
04 丟棄事務
直接看例子,在執行的最后,使用discard關鍵字對事務進行丟棄,那么事務執行過程中產生的key是沒有值的。
- 127.0.0.1:7397> multi
- OK
- 127.0.0.1:7397> set key_aa aa
- QUEUED
- 127.0.0.1:7397> set key_bb bb
- QUEUED
- 127.0.0.1:7397> set key_cc cc
- QUEUED
- 127.0.0.1:7397> discard
- OK
- 127.0.0.1:7397> get key_aa
- (nil)
- 127.0.0.1:7397> get key_bb
- (nil)
- 127.0.0.1:7397> get key_cc
- (nil)
05 watch命令
有些場景中,需要在事務之前,確保事務中的key沒有被其他客戶端修改過,才執行事務,否則不執行事務,redis提供了watch命令來解決這類問題。
正確場景:
- 127.0.0.1:7397> watch key_a
- OK
- 127.0.0.1:7397> multi
- OK
- 127.0.0.1:7397> set key_a aaa
- QUEUED
- 127.0.0.1:7397> exec
- 1) OK
- 127.0.0.1:7397> get key_a
- "aaa"
使用watch監控key_a的值,在exec之前,key_a的值沒有被其他事務修改過,那么exec的結果是成功的。
錯誤場景:
- 127.0.0.1:7397> watch key_a
- OK
- 127.0.0.1:7397> get key_a
- "aaa"
- ----------------------------------------
- 此時在另外一個session上執行set key_a aaaaaa
- ----------------------------------------
- 127.0.0.1:7397> multi
- OK
- 127.0.0.1:7397> set key_a a
- QUEUED
- 127.0.0.1:7397> exec
- (nil)
在watch的過程中,其他session對key_a的值進行了修改,那么會造成exec執行失敗,返回nil
06 總結
1、Redis事務就是一次性、順序性、排他性的執行一個隊列中的一系列命令,分為三個過程:開始事務、命令入隊、執行事務。
2、Redis提供了簡單的事務,使用multi、exec、discard這三個命令來控制
3、exec命令前,所有的原子操作都被放在隊列中緩存,并不會真正執行
4、Redis事務不存在隔離級別的概念
5、事務中的單條命令是原子執行的,但是事務本身不保證原子性,沒有回滾機制
以上就是Redis 事務相關總結的詳細內容,更多關于Redis 事務的資料請關注服務器之家其它相關文章!