Redis09-Redis事務(wù)
前言
上一篇我們介紹了Redis的持久化,這一篇我們接著來學(xué)習(xí)Redis的事務(wù)。將從如下幾個(gè)方面進(jìn)行闡述,事務(wù)的介紹,Redis事務(wù)的介紹,Redis事務(wù)與數(shù)據(jù)庫(kù)事務(wù)的區(qū)別。
事務(wù)
何為事務(wù)呢?我的理解是事務(wù)是一種機(jī)制,是一個(gè)不可分割的工作單元,要么都執(zhí)行,要么都不執(zhí)行。其具有如下四個(gè)特性:
原子性(Atomicity)
原子性是指事務(wù)是一個(gè)不可分割的工作單元,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
一致性(Consistency)
一致性是指事務(wù)前后數(shù)據(jù)的完整性必須保持一致。
隔離性(Isolation)
隔離性是指多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行,也就是說事務(wù)之間是相互隔離的。
持久性(Durability)
持久性是指一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)的改變是持久的,接下來即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。在關(guān)系型數(shù)據(jù)庫(kù)中,事務(wù)執(zhí)行完之后,執(zhí)行結(jié)果就寫到了硬盤中。
上面就是事務(wù)的四個(gè)特性,簡(jiǎn)稱ACID。關(guān)系型數(shù)據(jù)庫(kù)事務(wù)都滿足這四個(gè)特性。
Redis的事務(wù)
下面就是一個(gè)Redis事務(wù)的使用示例。
Redis事務(wù)的簡(jiǎn)介
Redis事務(wù)其實(shí)就是將多個(gè)命令包裹起來,一次性執(zhí)行。默認(rèn)是不開啟事務(wù)的。Redis事務(wù)從開始到執(zhí)行會(huì)經(jīng)歷如下三個(gè)階段:
開始事務(wù)MULTI
我們通過MULTI命令將執(zhí)行該命令的客戶端從非事務(wù)狀態(tài)切換至事務(wù)狀態(tài),通過在客戶端狀態(tài)的flags屬性中打開REDIS_MULIT標(biāo)識(shí)來完成的。
127.0.0.1:6379> MULTI OK
1
2
命令入隊(duì)
如果客戶端正處于事務(wù)狀態(tài)時(shí),當(dāng)添加新命令時(shí),首先會(huì)判斷這個(gè)命令是否是EXEC,DISCARD,WATCH或者M(jìn)ULTI這四個(gè)命令, 如果不是的話則會(huì)把命令放入事務(wù)隊(duì)列中,每個(gè)Redis客戶端都有自己的事務(wù)隊(duì)列,它是一個(gè)multlCmd類型的數(shù)組,數(shù)組中的每個(gè)multlCmd類型的數(shù)組,數(shù)組中的每個(gè)multiCmd結(jié)構(gòu)都保存了一個(gè)已入隊(duì)命令的相關(guān)信息,包括指向命令實(shí)現(xiàn)函數(shù)的指針,命令的參數(shù),以及參數(shù)的數(shù)量,它以先進(jìn)先出(FIFO)的方式保存入隊(duì)的命令,較先入隊(duì)的命令會(huì)被放到數(shù)組前面,而較后入隊(duì)的命令會(huì)被放在數(shù)組的后面。
127.0.0.1:6379> set name zhangsan QUEUED
1
2
執(zhí)行事務(wù)EXEC
當(dāng)一個(gè)處于事務(wù)狀態(tài)的客戶端向服務(wù)器發(fā)送EXEC命令時(shí),這個(gè)EXEC命令將立即被服務(wù)器執(zhí)行。服務(wù)器會(huì)遍歷這個(gè)客戶端的事務(wù)隊(duì)列,執(zhí)行隊(duì)列中保存的所有命令,最后將執(zhí)行命令所得的結(jié)果全部返回給客戶端。
127.0.0.1:6379> exec 1) OK 2) "zhangsan" 3) OK
1
2
3
4
Redis事務(wù)的相關(guān)特性
Redis事務(wù)并不完全具有ACID這四種特性,它只具有一致性和隔離性。原因如下:
Redis使用單線程的方式來執(zhí)行事務(wù)(以及事務(wù)隊(duì)列中的命令),并且服務(wù)器保證,在執(zhí)行事務(wù)期間不會(huì)中斷事務(wù),因此,Redis中的事務(wù)總是以串行的方式執(zhí)行,并且事務(wù)是具有隔離性的。
Redis事務(wù)不過是一組包裹起來的命令,Redis并沒有做特殊的持久化工作,所以一般而言Redis事務(wù)不具有持久性,Redis的持久性策略可以看上一篇文章。
Redis不支持事務(wù)回滾機(jī)制(rollback),即使事務(wù)隊(duì)列中的某個(gè)命令在執(zhí)行期間出現(xiàn)了錯(cuò)誤,整個(gè)事務(wù)也會(huì)繼續(xù)執(zhí)行下去,直到將事務(wù)隊(duì)列中的所有命令都執(zhí)行完畢為止,所以,Redis事務(wù)不支持原子性。如下圖所示:
事務(wù)總是具有一致性的。即事務(wù)執(zhí)行前后數(shù)據(jù)是一致的。
Redis事務(wù)的實(shí)現(xiàn)原理
Redis實(shí)現(xiàn)事務(wù),是基于COMMANDS隊(duì)列的,也就是說,如果沒有開啟事務(wù),command將會(huì)被立即執(zhí)行并返回執(zhí)行結(jié)果,并且直接保存在內(nèi)存中,如果事務(wù)開啟,command不會(huì)被立即執(zhí)行,而是排入隊(duì)列并返回排隊(duì)狀態(tài)(具體依賴于客戶端(例如:spring-data-redis)自身實(shí)現(xiàn)),調(diào)用EXEC才會(huì)執(zhí)行COMMANDS隊(duì)列。
WATCH命令
WATCH命令是一個(gè)樂觀鎖,它可以在EXEC命令執(zhí)行之前,監(jiān)視任意數(shù)量的數(shù)據(jù)庫(kù)鍵,并在EXEC命令執(zhí)行時(shí),檢查被監(jiān)視的鍵是否至少有一個(gè)已經(jīng)被修改過了,如果是的話,服務(wù)器將拒絕執(zhí)行事務(wù),并向客戶端返回代表事務(wù)執(zhí)行失敗的空回復(fù)。如下所示:
與MySQL事務(wù)的區(qū)別
事務(wù)的命令不同
MySQL事務(wù)的使用如下:
BEGIN : 顯式地開啟一個(gè)事務(wù) COMMIT: 提交事務(wù) ROLLBACK: 結(jié)束用戶的事務(wù),并撤銷正在進(jìn)行的所有未提交的修改
1
2
3
而Redis事務(wù)的使用如下:
MULTI: 標(biāo)記事務(wù)的開始 EXEC: 執(zhí)行事務(wù)的commands 隊(duì)列 DISCARD: 結(jié)束事務(wù),并清除commands隊(duì)列;
1
2
3
默認(rèn)狀態(tài)不同
MySQL會(huì)默認(rèn)開啟一個(gè)事務(wù),且缺省設(shè)置是自動(dòng)提交,即每成功執(zhí)行一個(gè)SQL,一個(gè)事務(wù)就會(huì)馬上COMMIT,所以不能Rollback。當(dāng)然,我們?cè)谕粋€(gè)事務(wù)中執(zhí)行多個(gè)SQL時(shí),如果某個(gè)SQL執(zhí)行失敗了,則這個(gè)事務(wù)就會(huì)回滾掉。
Redis默認(rèn)不會(huì)開啟事務(wù),即command會(huì)立即執(zhí)行,而不會(huì)排隊(duì),并且不支持Rollback。
實(shí)現(xiàn)原理不同
MySQL實(shí)現(xiàn)事務(wù),是基于UNDO/REDO日志,UNDO日志記錄修改前狀態(tài),ROLLBACK命令是基于UNDO日志實(shí)現(xiàn)的。
REDO記錄修改后的狀態(tài),COMMIT命令是基于REDO日志實(shí)現(xiàn)的。
在MySQL中無(wú)論是否開啟日志,SQL都會(huì)立即執(zhí)行并返回結(jié)果,只是事務(wù)開啟后執(zhí)行后的狀態(tài)記錄在REDO日志,執(zhí)行COMMIT之后,數(shù)據(jù)才會(huì)被寫入磁盤。
參考
《Redis設(shè)計(jì)與實(shí)現(xiàn)》
總結(jié)
本文簡(jiǎn)單介紹了Redis事務(wù)并將其與MySQL事務(wù)做了一下對(duì)比。Redis事務(wù)只有一致性和隔離性兩種特性,不支持原子性和持久性。其實(shí)現(xiàn)原理是基于COMMANDS隊(duì)列的,開啟事務(wù)之后,命令不會(huì)被立即執(zhí)行,而是排入隊(duì)列并返回排隊(duì)狀態(tài)。
Redis 數(shù)據(jù)庫(kù)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。