作為一個nosql
數據庫,事務是必要功能.但是redis我們是可以理解為它不支持事務操作的,因為它的特征完全不滿足我們對事物的正常理解
ps:我不知道是誰一開始提出redis支持事務的,但是我更傾向於這是redis的
多命令
功能
multi
這個命令單詞意思已經說明了一切,我只能理解為中文文檔一廂情願了
事務的使用
1. 開啟事務
命令:multi
127.0.0.1:6379> multi
OK
執行該命令后,連接會進入事務模式
2.執行操作
可以執行任意的redis數據操作命令,那么執行操作會進入一個待執行隊列
127.0.0.1:6379> set name zhangsan
QUEUED
127.0.0.1:6379> set age 34
QUEUED
3.提交事務
命令:exec
提交之后,待執行隊列
中的命令將執行
127.0.0.1:6379> exec
1) OK
2) OK
待執行隊列清除
清空隊列:discard
事務的具體情況處理
Redis事務的特點
1.沒有隔離級別的概念
開啟事務之后的操作全部是在待執行隊列
中緩存,並沒有真正執行,也就不存在事務內部的查詢要看到事務即將的更新,事務外部也不知道
2.不保證原子性
Redis對單條命令是保證原子性(比如批量msetnx
命令),但是如果事務不保證原子性(一致性),就沒有回滾的概念了.事務中任何命令的失敗,其余命令任會執行
可以這么說.Redis的以上兩個事務特征幾乎可以認為,redis沒有事務功能.更應該稱之為命令的打包執行.
那么為什么redis中要有事務?舉個例子:假設登錄的時候記錄登錄的ip(一條命令操作),接下再執行保存用戶的登錄消息操作(一條命令),假設獲取用戶的消息需要在另外一個系統中獲取,我們無法保證100%獲取到.但是這兩步操作在我們程序業務功能設計中應該被認為是登錄操作的單個功能起的影響.因為獲取用戶的登錄消息可能會失敗.那么就沒必要記錄ip了.redis恰恰提供事務名隊列的清空功能
可以怎么理解,如果你的(命令)操作步驟非常多,每一個命令都需要大量的其他非redis的操作才能保證接下來的業務進行,那么就需要redis的事務隊列功能一步一步記錄命令,在整個工程中如果發生了意外則清空隊列,正常則提交
所以我們應該在我們的程序代碼中保證一致性和隔離級別的功能而不是交給redis,方正redis的事務就是打包執行,任何利用是查詢設計的問題
在redis開啟事務的魅力multi
就可以知道,redis自己本身也沒有把這個功能稱之為事務.正確的叫法是多命令
3.若在待執行隊列
中存在語法性錯誤,exec
提交之后,其他正確命令也會被執行,這是單單的錯誤命令拋出異常
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name li si #錯誤的命令
QUEUED
127.0.0.1:6379> set money 100
QUEUED
127.0.0.1:6379> exec
1) (error) ERR syntax error
2) OK
如果是錯誤的命令名(比如
setnx
寫成setnn
,則不能稱之為語法錯誤),如果在隊列中出現了類似錯誤,則整個隊列不成功
watch
語法:watch key
watch類似於樂觀鎖
如果在watch
命令觀測一個key
之后,開啟事務后修改該key
.這個時候如果有其它連接修改了key
,則會導致事務執行失敗,在這個事務的其他操作也是失敗
exec
之后,watch
命令監控取消
watch
命令可以說是redis的事務功能最關鍵的運用了,在使用了watch
之后可以保證一定的原子性和數據安全